JavaScript/Node.js中迭代数组对象的高效方式

7

我定义了一个对象

var Person = function(name,age,group){
this.name = name,
this.age = age,
this.group = group
}

var ArrPerson = [];
ArrPerson.push(new Person("john",12,"M1"));
ArrPerson.push(new Person("sam",2,"M0"));

现在我需要一种有效的机制来判断对象数组ArrPerson是否包含特定的名称?

我知道我们可以使用for循环迭代数组并检查。假设数组很大,有没有其他更有效的方法?


你只是在寻找 name 属性还是其他属性? - Nina Scholz
Thomas说得对 - 如果效率是主要标准,你不应该使用普通数组。 - Alnitak
1
如果你只有一个(未排序的)数组,除了迭代它之外,你别无选择。 - Bergi
常规的for循环是最快的方法。此外,如果您只需要一个项目,您可以打破循环。 - Vsevolod Goloviznin
我需要先检查姓名,如果姓名匹配,我需要检索年龄和组。 - bharz629
4个回答

9

您可以使用数组的filter或find方法。

ArrPerson.find(p=>p.name=='john')
ArrPerson.filter(p=>p.name=='john')

find方法从数组开头开始搜索,并在找到一个匹配元素时停止搜索。最坏情况下,如果正在搜索的元素是数组中的最后一个元素或者不存在,这个方法的时间复杂度将会是O(n)。这意味着该方法将进行n次检查(n是数组的长度),直到它停止。

filter方法总是执行O(n),因为每次都需要搜索整个数组以找到每个匹配的元素。

尽管可以通过创建新的数据结构来使某些操作更快(理论上),例如:

var hashmap = new Map();
var ArrPerson = [];
ArrPerson.push(new Person("john",12,"M1"));
hashmap.set("john",true);

这个ES6 Map将根据它包含的名称保留整个数组的索引。如果您想查看数组是否包含某个名称,可以执行以下操作:

hashmap.has('john')//true

这种方法的时间复杂度为O(1)。它只需要查看一次地图,以确定该名称是否存在于您的数组中。此外,您可以在地图内跟踪数组索引:

var index = ArrPerson.push(new Person("john",12,"M1"));
var map_indexes = hashmap.get("john");
if(map_indexes){
  map_indexes.push(index-1);
  hashmap.set("john",map_indexes);
}else{
  hashmap.set("john",[index-1]);
}
map_indexes = hashmap.get("john"); //an array containing the ArrPerson indexes of the people named john
//ArrPerson[map_indexes[0]] => a person named john
//ArrPerson[map_indexes[1]] => another person named john ...

采用这种方法,你不仅可以知道数组中是否有一个特定名称的人,还可以使用O(1)查找整个对象。

请注意,如果您想要其他标准,此映射将仅按名称索引人员,您需要另一个映射。同时,保持两个数据结构同步并不容易(从数组中删除一个元素也应该从映射中删除等)。

总之,如常所言,提高速度就意味着在我们的示例中牺牲了其他东西,例如内存和代码复杂性。


6
  • 使用ES5数组方法,如map,filter,reduce等
  • 使用forEach
  • 使用原生的for循环

例如:filter,map,reduce等方法可以遍历数组中的每个项或对象。

ArrPerson.filter(function(item){
       console.log(item)
   });

forEach :也会遍历数组中的每个项目/对象

 ArrPerson.forEach(function(key,value){
     console.log(key);
     console.log(value)
  })

这个问题中提到了巨大的数组,因此使用原生的for循环比上述任何方法都要快,并且缓存长度可以提高几毫秒(毫秒)。

https://jsperf.com/native-map-versus-array-looping

for(var i = 0, len = ArrPerson.length; i < len; i++){

}

5
ES5 数组方法 不是 异步的。它们确实需要一个回调函数,但该回调函数是 同步 调用的! - Alnitak

0

类似这样的代码应该可以运行。

    var Person = function(name,age,group){
    this.name = name,
    this.age = age,
    this.group = group
    }

    var ArrPerson = [];
    ArrPerson.push(new Person("john",12,"M1"));
    ArrPerson.push(new Person("sam",2,"M0"));

    for(var key in ArrPerson){
        if(ArrPerson[key].name === 'john'){
        //do something
          alert(ArrPerson[key].name);
        }
        }


0

假设您想要检查所有内容,并且没有其他索引,那么问题仍然是O(n)。您可以使用.filter()过滤并返回符合条件的数组。或者,您可以使用其他数据结构按照您想要搜索的方式进行索引。

var Person = function(name, age, group) {
  this.name = name,
    this.age = age,
    this.group = group
}

var ArrPerson = [];
ArrPerson.push(new Person("john", 12, "M1"));
ArrPerson.push(new Person("sam", 2, "M0"));

function findByName(arr, name) {
  return arr.filter(function(o) {
    return o.name == name;
  });
}

document.write(JSON.stringify(findByName(ArrPerson, "john")));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接