【问题标题】: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 语言来做,而是从计算机科学的角度来看,这将是最好的实施。

标签: javascript c++ arrays dynamic


【解决方案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/

      【讨论】:

        猜你喜欢
        • 2012-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-26
        • 1970-01-01
        • 2019-08-19
        • 2014-09-23
        • 1970-01-01
        相关资源
        最近更新 更多