有没有更好的方法来实现对包含结构化数据的数组的搜索?

Posted

技术标签:

【中文标题】有没有更好的方法来实现对包含结构化数据的数组的搜索?【英文标题】:Is there a better way to implement a search on an array containing structured data? 【发布时间】:2015-12-26 07:07:21 【问题描述】:

我经常遇到需要动态创建一个包含特定数据的对象数组,这也需要一个搜索方法,例如:

Javascript

var people = [];
var addPerson = function(name, age) 
    people.push(name:name, 
                 age:age);

getArrayID = function (name) 
    for(var i = 0 ; i < main.nodes.length ; i++) 
        if(main.nodes[i].name == name)
            return i;
        
    return -1;


addPerson("Person A", 22);
addPerson("Person B", 23);
console.log(people[getArrayID("PersonB")].age);
// Result: 23

虽然这可行,但感觉它是解决“标记”数据问题的不正确解决方案,因为它通常还包含 getArrayName(id) 方法。

如果可能的话,我希望看到使用像 Javascript 这样的“松散”语言(对象和数组可以用字符串命名)和像 这样更严格的语言的解决方案>C++Java

【问题讨论】:

要求这是两种不同的语言并不是一个好主意。这就像在一个问题中提出两个问题,这意味着你会得到一些更关注一个问题的答案,而另一些则更关注另一个问题。为什么不先询问一种语言,然后,如果仍然需要且有意义,请针对另一种语言发布第二个问题? 欢迎来到 SO。请访问help center 看看在这里问什么。因此,它是题外话,可能属于 codereview @jogojapan 我对简化的解决方案以及处理此问题的常用方法都感兴趣,因为我认为这是任何使用动态数组的程序中的常见功能。我是一名自学成才的程序员,所以学习解决方案以及解决方案背后的理论让我很感兴趣,这不仅仅是看看如何用 X 和 Y 语言来做,而是从计算机科学的角度来看,这将是最好的实施。 【参考方案1】:

有几种方法可以做到这一点。

[].find()

var people = [];
var addPerson = function(name, age) 
  people.push(
    name: name,
    age: age
  );


// will return ONE person or null
getPerson = function(name) 
  return people.find(function(person) 
    return person.name == name;
  );


addPerson("Person A", 22);
addPerson("Person B", 23);

var pers = getPerson("Person B");
// we must check pers is not null/undefined
if (pers) 
  console.log(pers.age);
  document.write(pers.age);

[].filter()

var people = [];
var addPerson = function(name, age) 
  people.push(
    name: name,
    age: age
  );


// will return an array of persons (can be empty)
getPerson = function(name) 
  return people.filter(function(person) 
    return person.name == name;
  );


addPerson("Person A", 22);
addPerson("Person B", 23);

var pers = getPerson("Person B")[0];
// we must check pers is not null/undefined
if (pers) 
  console.log(pers.age);
  document.write(pers.age);

【讨论】:

是的,你需要确认'pers'不是未定义的。【参考方案2】:

如果人们的name 是独一无二的,我会选择使用object 而不是数组。这样您就不必每次都搜索整个数组并从原生“搜索性能”中获益。

类似这样的:

var people = ; 
var addPerson = function(name, age)  
    people[name] = name:name, age:age; 
 
addPerson("Person A", 22);
addPerson("Person B", 23); 
var person = people["PersonB"];
console.log(person && person.age); // Result: 23

【讨论】:

【参考方案3】:

javascript 中,您可以将Array.prototype.reduce() 用于混合用途,例如仅返回索引或特殊模式。

此解决方案的特点是具有搜索参数的对象,例如要搜索的属性和要查找的值。结果是一个数组,其中包含数组的所有匹配模式的索引。

function setCondition(condition) 
    var key = Object.keys(condition)[0],
        value = condition[key];
    return function (r, a, i) 
        if (a[key] === value) 
            r.push(i);
        
        return r;
    


var people = [ name: 'Person A', age: 22 ,  name: 'Person B', age: 23 ],
    indices = people.reduce(setCondition( name: 'Person B' ), []);

document.write('<pre>' + JSON.stringify(indices, 0, 4) + '</pre>');

【讨论】:

【参考方案4】:

是的。使用 lodash。有了它,您可以将这种方式简化:

var person = _.find(people,  "name": "Person B" );
if (person !== undefined) 
    var age = 'age' in person ? person.age:'not available';
    console.log('Age: ',age);
 else 
    console.log("Couldn't find that guy");

这是一个 jsfiddle:

https://jsfiddle.net/mckinleymedia/c2nnknsh/1/

【讨论】:

以上是关于有没有更好的方法来实现对包含结构化数据的数组的搜索?的主要内容,如果未能解决你的问题,请参考以下文章

在Objective-C中搜索和获取多维数组的索引

jq ~ 有没有更好的方法来折叠单个对象数组?

有没有更好的方法来为 Python 中的集群分配数组生成成员矩阵(单热数组)? [复制]

有没有更好的方法来创建“抽象”线性搜索? [复制]

如何检查数组是否包含JavaScript中的对象?

二叉搜索树 思想 JAVA实现