我怎样才能简单直接地找到满足某些条件的对象数组中的索引?

例如,给定这个输入:

var hello = {
    hello: 'world',
    foo: 'bar'
};
var qaz = {
    hello: 'stevie',
    foo: 'baz'
}

var myArray = [];
myArray.push(hello, qaz);

我如何搜索myArray找到其hello属性等于'stevie'的元素的索引(在这种情况下,结果应该是1)?


当前回答

我更喜欢使用findIndex()方法:

 var index = myArray.findIndex('hello','stevie');

Index会给出索引号。

其他回答

我已经做了一个通用函数来检查下面是代码&适用于任何对象

function indexOfExt(list, item) {
    var len = list.length;

    for (var i = 0; i < len; i++) {
        var keys = Object.keys(list[i]);
        var flg = true;
        for (var j = 0; j < keys.length; j++) {
            var value = list[i][keys[j]];
            if (item[keys[j]] !== value) {
                flg = false;
            }
        }
        if (flg == true) {
            return i;
        }
    }
    return -1;
}

var items = [{ "hello": 'world', "foo": 'bar' }];
var selectedItem = { "hello": 'world', "foo": 'bar' };
alert(items.indexOf(selectedItem));
alert(indexOfExt(items, selectedItem));

第一个警报将返回-1(表示未找到匹配),第二个警报将返回0(表示找到匹配)。

我喜欢Pablo的回答,但是array# indexOf和array# map并不适用于所有浏览器。下划线将使用本机代码,如果它是可用的,但也有回退。另外,它有pluck方法来做Pablo的匿名映射方法所做的事情。

var idx = _.chain(myArray).pluck("hello").indexOf("Stevie").value();

我在这里对各种答案做了一些性能测试,任何人都可以自己运行:

https://jsperf.com/find-index-of-object-in-array-by-contents

根据我在Chrome中的初始测试,以下方法(使用原型内部设置的for循环)是最快的:

Array.prototype.indexOfObject = function (property, value) {
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][property] === value) return i;
    }
    return -1;
}

myArray.indexOfObject("hello", "stevie");

这段代码是对Nathan Zaetta的答案稍加修改的版本。

在性能基准测试中,我尝试将目标放在1000对象数组的中间(索引500)和末尾(索引999),即使我将目标放在数组中的最后一项(意味着它必须循环遍历数组中的每一项才能找到),它仍然是最快的。

这个解决方案还有一个好处,就是对于重复执行来说是最简洁的,因为只需要重复最后一行:

myArray.indexOfObject("hello", "stevie");

试试这个:

console.log(Object.keys({foo:"_0_", bar:"_1_"}).indexOf("bar"));

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Array.prototype.findIndex在除IE(非边缘)之外的所有浏览器中都支持。但是提供的填充材料很好。

var indexOfStevie = myArray.findIndex(i => i.hello === "stevie");

map的解决方案是可以的。但每次搜索都要遍历整个数组。这只是findIndex的最坏情况,它一旦找到匹配项就会停止迭代。

没有一个简洁的方法(当开发者不得不担心IE8时),但这里有一个常见的解决方案:

var searchTerm = "stevie",
    index = -1;
for(var i = 0, len = myArray.length; i < len; i++) {
    if (myArray[i].hello === searchTerm) {
        index = i;
        break;
    }
}

或作为一个函数:

function arrayObjectIndexOf(myArray, searchTerm, property) {
    for(var i = 0, len = myArray.length; i < len; i++) {
        if (myArray[i][property] === searchTerm) return i;
    }
    return -1;
}
arrayObjectIndexOf(arr, "stevie", "hello"); // 1

只是一些注释:

不要用于…在数组的循环中 一旦找到“指针”,请确保跳出循环或返回函数。 注意对象相等性

例如,

var a = {obj: 0};
var b = [a];
b.indexOf({obj: 0}); // -1 not found