在对象数组中,找到属性与搜索匹配的对象索引的最快方法

IT技术 javascript arrays indexof
2021-02-24 22:42:15

我一直在四处冲浪,试图找到一种有效的方法来做到这一点,但一无所获。我有一个看起来像这样的对象数组:

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

我想要做的是找到 id 等于的对象的 INDEXES,例如,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,因为它可能应该。

6个回答

也许您想使用诸如“map”之类的高阶函数。假设您想按 'field' 属性搜索:

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];
@ZeroAbsolute 您的应用函数(传递给 map)可以返回一个哈希字符串,该字符串应该为您的标准给出的每个可能的组合提供一个唯一的键。例如:function hashf(el) { return String(el.id) + "_" + String(el.name); }这只是一个提示:elementPos = array.map(hashf(x)).indexOf(hash({id:3, name:'Pablo'}));显然,我提供的散列函数并非对所有情况'_'有效,因为它可能构成您的值的一部分,但这只是一个快速示例,您可以找出不同的散列方法。
2021-04-20 22:42:15
大家好,map, indexOf您可以只使用一种叫做findIndex......的方法,而不是使用两种方法。例如:[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3}) OR [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)
2021-04-28 22:42:15
@NathanC.Tresch 它返回 -1,因为indexOf当它无法找到给定值时,这是返回值。
2021-04-29 22:42:15
如果找不到它会返回什么?我假设-1,只是好奇。我会实验。
2021-04-30 22:42:15
这个答案很棒,因为它实际上通过提供索引来回答问题:)
2021-05-10 22:42:15

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

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)

这个答案至少比上面接受的答案快 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 毫秒。
2021-04-18 22:42:15
这是获取INDEX的正确方法 const index = this.pages.findIndex(object => { return object.id === id; }); console.log('index', index);
2021-04-21 22:42:15
这个答案是最有效的,因为它不会迭代整个数组。选定的答案将映射完整的数组,然后 findIndex 将遍历整个数组一次
2021-04-24 22:42:15
我相信这是最优雅的解决方案。对于那些担心向后兼容性的人,您可以findIndexdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-05-01 22:42:15
我在 ES6 lint 工具中收到一条警告,指出obj.id == 3此处使用的obj.id === 3运算符会导致意外的类型转换,因此请改用运算符,它会测试相等的值和类型。
2021-05-12 22:42:15

新的 Array 方法.filter()可以很好地解决这个问题:

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery 也可以使用.grep()做到这一点

编辑:值得一提的是,这两个函数只是在引擎盖下迭代,它们与滚动您自己的过滤器函数之间不会有明显的性能差异,但为什么要重新发明轮子。

这不会返回索引。
2021-04-26 22:42:15
+1,我总是忘记对象上的内置函数。
2021-04-28 22:42:15
这不会返回索引。
2021-05-06 22:42:15
这不能回答这个具体问题,但对我有很大帮助!谢谢!
2021-05-13 22:42:15

如果您关心性能,请不要使用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);
我已经扩展了基准jsben.ch/19PxA,这第 4 个块是 Chrome 中最快的。-> items.map(function(x) {return x.id; }).indexOf(find);
2021-04-15 22:42:15
我认为这应该标记为答案。这显示了最快的方式和较慢的方式。
2021-04-22 22:42:15
Block 2 现在在 chrome 上也更快
2021-04-24 22:42:15
在您的基准测试中,块 2(使用 findIndex)实际上对我来说更快(在 Microsoft Edge Chromium 83.0.474.0 上)
2021-04-30 22:42:15
感谢您提供此比较!非常有趣的是性能有多少变化 - 包括哪种方法更快,具体取决于用于运行它们的浏览器/JavaScript 引擎。
2021-05-14 22:42:15
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 我们得到记录的索引。