在一个对象数组中,查找属性与搜索匹配的对象的索引的最快方法是什么?

170

我在网上查找了一下,试图找到一种有效的方法来实现这个,但是却一无所获。我的一个对象数组长这样:

array[i].id = some number;
array[i].name = some name;

我想做的是找到id等于0、1、2、3或4中任意一个的对象的索引。

我想可以这样做:

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

虽然这样可以工作,但它看起来非常昂贵和缓慢(更不用说丑陋),特别是如果array.length可能很大。有什么想法可以让它变得更好一些吗?我想过使用array.indexOf,但我不知道如何强制语法。

array.indexOf(this.id === 0);

例如,返回undefined,正如它应该的那样。


1
如果你有一个普通的数组,你所能做的就是迭代。这就是数组的本质,一堆按照数组索引排序的对象。 - Dave Newton
2
今天刚看到这篇文章,对于所有的后来者,在ECMAScript 2015中有一个新的数组方法Array.prototype.findIndex()。不过,被接受的答案真的很棒。 - Conrad Lo
我是ES6语法的粉丝(如果需要支持旧版浏览器,则使用polyfills)。ES7+ES8将成为未来。 - Fr0zenFyr
只是供参考,如果您想快速查找,则最好不要使用数组,而应改用字典(Id,对象)。 - Worthy7
19个回答

431

也许您想使用高阶函数,例如“map”。 假设您想按“field”属性搜索:

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

10
这个回答很棒,因为它提供了索引,实际上回答了问题 :) - counterbeing
3
你传递给map的应用函数可以返回一个哈希字符串,它应该为您的条件给出的每个可能组合提供一个唯一的键。例如: function hashf(el) { return String(el.id) + "_" + String(el.name); }。这只是一个提示: elementPos = array.map(hashf(x)).indexOf(hash({id:3, name:'Pablo'})); 显然,我提供的哈希函数并不适用于所有情况,因为'_'可能成为您的值的一部分,但这只是一个快速的例子,您可以想出不同的哈希方法。 - Pablo Francisco Pérez Hidalgo
1
一个快速的示例供您复制粘贴,以便尝试Pablo对这个非常普遍的问题的简单解决方案!`var arrayOfObjects = [
{ a: 1, aa: "two"}, // 0
{ a: "asdf", aa: 2}, // 1
{ a: "cat", aa: "dog"} // 2
]; var elementPos = arrayOfObjects.map(function(x) {return x.aa; }).indexOf('dog');
var objectFound = arrayOfObjects[elementPos];
console.log(elementPos, objectFound); // 2 { a: 'cat', aa: 'dog' }`
- Rick
4
大家好,不必使用mapindexOf这两种方法,您只需使用称为findIndex的一种方法即可...... 例如:[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3}) 或者 [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3) - Umair Ahmed
1
仅在该项仅出现一次时有效。如果该项出现多次,则indexOf方法仅返回第一个出现的位置。因此,它将不会提供包含该项所有出现位置的数组。 - Ioannis K. Moutsatsos
显示剩余9条评论

103

在数组中查找元素索引最简单、最易用的方法。

ES5 语法: [{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

ES6 语法: [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)


5
我认为这是最优雅的解决方案。对于那些担心向后兼容性的人,你可以在 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex 找到“findIndex”的polyfill。 - mrogers
3
我的 ES6 代码检查工具提示我,这里使用的 obj.id == 3 运算符可能会导致意想不到的类型转换,建议改用测试相等值和类型的 obj.id === 3 运算符。请注意,不要改变原本的含义。 - thclark
5
这个答案比上面被接受的答案快了至少3.5倍。 使用 var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor); 花费了0.03500000002532033毫秒。 使用 [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3) 花费了0.00999999747378752毫秒。 - Ovidio Reyna
3
这个答案是最高效的,因为它不需要迭代整个数组。所选答案将映射完整的数组,然后使用findIndex来绑定一次迭代整个数组。 - Karun
2
这是获取 INDEX 的正确方法:const index = this.pages.findIndex(object => { return object.id === id; }); console.log('index', index); - Parth Developer

26
新的数组方法 .filter() 对此非常有效:
var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery也可以使用.grep()实现这个功能。

编辑:值得一提的是,这两个函数在内部都只是迭代操作,它们和自己编写的过滤函数之间不会有明显的性能差异,但为什么要重新发明轮子呢。


+1,我总是忘记对象上内置的这种函数。 - Tejs
64
这不会返回索引。 - Adam Grant
1
这并没有回答这个具体的问题,但是对我帮助很大!谢谢! - rochasdv
1
这不会返回索引。 - Rich

21

如果您关心性能,请不要使用findfiltermap或以上讨论的任何方法。

以下是演示最快方法的示例。这里是实际测试的链接。

设置块

var items = []

for(var i = 0; i < 1000; i++) {
    items.push({id: i + 1})
}

var find = 523

最快方法

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

较慢的方法

items.findIndex(item => item.id === find)

最慢的方法

items.map(item => item.id).indexOf(find);

10

由于常规数组 find 没有结果:

var one = {id: 1, name: 'one'};
var two = {id: 2, name:'two'}
var arr = [one, two] 
     
var found = arr.find((a) => a.id === 2) 

console.log(found === two) // true

console.log(arr.indexOf(found)) // 1


8
array.forEach(function (elem, i) {  // iterate over all elements of array
    indexes[elem.id] = i;           // take the found id as index for the
});                                 // indexes array and assign i

结果是一个查找列表,用于查找id。根据给定的id,我们可以得到记录的索引。

7

const index = array.findIndex(item => item.id === 'your-id');

这行代码将会返回数组中id等于your-id的那个元素的索引位置。

array = [ {id:1}, {id:2} ];

const index = array.findIndex(item => item.id === 2);

console.log(index);


6
var indices = [];
var IDs = [0, 1, 2, 3, 4];

for(var i = 0, len = array.length; i < len; i++) {
    for(var j = 0; j < IDs.length; j++) {
        if(array[i].id == ID) indices.push(i);
    }
}

5

使用 ES6 的新方法

let picked_element = array.filter(element => element.id === 0);

3
使用ES6的map函数:
let idToFind = 3;
let index = someArray.map(obj => obj.id).indexOf(idToFind);

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