对象数组中的indexOf方法?

获取包含对象的数组索引的最佳方法是什么?

想象一下这个场景:

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


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

现在我想有indexOf对象,其中hello属性是'stevie',在这个例子中,将是1

我是JavaScript的新手,我不知道是否有一个简单的方法,或者我应该构建自己的函数来做到这一点。

797593 次浏览
var idx = myArray.reduce( function( cur, val, index ){


if( val.hello === "stevie" && cur === -1 ) {
return index;
}
return cur;


}, -1 );

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

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

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

人力资源/ > < p > < 没有一个简洁的方法 (当开发者不得不担心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

只是一些注释:

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

例如,

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

请看这个例子:http://jsfiddle.net/89C54/

for (i = 0; i < myArray.length; i++) {
if (myArray[i].hello === 'stevie') {
alert('position: ' + i);
return;
}
}

它从零开始计数。

或者原型它:

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


myArr.indexOfObject("name", "stevie");

我认为你可以用地图函数在一行中解决它:

const pos = myArray.map(e => e.hello).indexOf('stevie');

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

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

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

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

index将为您提供索引号。

你可以创建自己的原型来做到这一点:

喜欢的东西:

Array.prototype.indexOfObject = function (object) {
for (var i = 0; i < this.length; i++) {
if (JSON.stringify(this[i]) === JSON.stringify(object))
return i;
}
}
array.filter(function(item, indx, arr){ return(item.hello === 'stevie'); })[0];

注意[0]

Antonio Laguna的答案中使用reduce是正确的。

抱歉这么简短……

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

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(表示找到匹配)。

短暂的

myArray.indexOf('stevie','hello')

用例:

  /*****NORMAL****/
[2,4,5].indexOf(4) ;//OUTPUT 1
/****COMPLEX*****/
[{slm:2},{slm:4},{slm:5}].indexOf(4,'slm');//OUTPUT 1
//OR
[{slm:2},{slm:4},{slm:5}].indexOf(4,function(e,i){
return e.slm;
});//OUTPUT 1
/***MORE Complex**/
[{slm:{salat:2}},{slm:{salat:4}},{slm:{salat:5}}].indexOf(4,function(e,i){
return e.slm.salat;
});//OUTPUT 1

API:

    Array.prototype.indexOfOld=Array.prototype.indexOf


Array.prototype.indexOf=function(e,fn){
if(!fn){return this.indexOfOld(e)}
else{
if(typeof fn ==='string'){var att=fn;fn=function(e){return e[att];}}
return this.map(fn).indexOfOld(e);
}
};

这是在数组中查找对象索引的方法

    var myArray = [{  hello: 'world',
foo: 'bar'
},{
hello: 'stevie',
foo: 'baz'
}];






for (i = 0; i < myArray.length; i++) {
if (myArray[i].hello === 'stevie') {
alert('position: ' + i);
return;
}
}

underscore.js图书馆使用_.findIndex

以下是示例 # EYZ0 < / p >

这无需自定义代码即可实现

var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true

注意:这并没有给出实际的索引,它只告诉你的对象是否存在于当前的数据结构中

使用ES6 # EYZ0方法,没有lodash或任何其他库,你可以写:

function deepIndexOf(arr, obj) {
return arr.findIndex(function (cur) {
return Object.keys(obj).every(function (key) {
return obj[key] === cur[key];
});
});
}

这将比较对象的直接属性,但不会递归到属性中。

如果你的实现还没有提供findIndex(大多数没有),你可以添加一个轻量级的填充来支持这个搜索:

function deepIndexOf(arr, obj) {
function findIndex = Array.prototype.findIndex || function (pred) {
for (let i = 0; i < this.length; ++i) {
if (pred.call(this, this[i], i)) {
return i;
}
}


return -1;
}


return findIndex.call(arr, function (cur) {
return Object.keys(obj).every(function (key) {
return obj[key] === cur[key];
});
});
}

(来自我对这种欺骗的回答)

除了@Monika Garg回答,你还可以使用findIndex()(对于不受支持的浏览器有polyfill)。

我看到人们对这个答案投了反对票,我希望他们这么做是因为语法错误,因为在我看来,这是最优雅的方式。

如果数组中的元素满足提供的测试函数,则findIndex()方法返回数组中的索引。否则返回-1。

例如:

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


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


var index = myArray.findIndex(function(element) {
return element.hello == 'stevie';
});


alert(index);

试试这个:

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

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

简单:

myArray.indexOf(myArray.filter(function(item) {
return item.hello == "stevie"
})[0])

你可以使用原生和方便的函数Array.prototype.findIndex():

如果数组中的元素满足提供的测试函数,则findIndex()方法返回数组中的索引。否则返回-1。

只是需要注意的是,它不支持Internet Explorer, Opera和Safari,但你可以使用下面链接提供的Polyfill。

更多信息:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

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


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


var index = myArray.findIndex(function(element, index, array) {
if (element.hello === 'stevie') {
return true;
}
});
alert('stevie is at index: ' + index);

你可以简单地使用

const someId = 2;
const array = [{id:1}, {id:2}, {id:3}];
const index = array.reduce((i, item, index) => item.id === someId ? index : i, -1);
alert('someId ' + someId + ' is at index ' + index);

没有下划线,没有for,只有一个略读。

在ES2015中,这很简单:

myArray.map(x => x.hello).indexOf('stevie')

或者,更大的数组可能会有更好的性能:

myArray.findIndex(x => x.hello === 'stevie')

如果你只对这个职位感兴趣,请参阅@Pablo的回答

# EYZ0

然而,如果你期待着找到元素(即,如果你正在考虑做这样的myArray[pos]),有一个更高效的一行的方法来做它,使用filter

# EYZ0

参见性能结果(~ +42% ops/sec): # EYZ0 < / p >

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

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");
var hello = {hello: "world",  foo: "bar"};
var qaz = {hello: "stevie", foo: "baz"};
var myArray = [];
myArray.push(hello,qaz);


function indexOfObject( arr, key, value   ) {
var j = -1;
var result = arr.some(function(obj, i) {
j++;
return obj[key] == value;
})


if (!result) {
return -1;
} else {
return j;
};
}


alert(indexOfObject(myArray,"hello","world"));

如果你的对象与你在数组中使用的对象是同一个对象,你应该能够以同样的方式获取对象的索引,就像它是一个字符串一样。

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


var qazCLONE = { // new object instance and same structure
hello: 'stevie',
foo: 'baz'
}


var myArray = [hello,qaz];


myArray.indexOf(qaz) // should return 1
myArray.indexOf(qazCLONE) // should return -1

我比较了几种方法,得到了一个最快解决这个问题的结果。这是一个for循环。它比其他方法快5倍以上。

下面是测试页面:https://jsbench.me/9hjewv6a98

然而,大多数其他答案都是有效的。有时候,最好在你要使用它的地方创建一个简短的函数。

// indexOf wrapper for the list of objects
function indexOfbyKey(obj_list, key, value) {
for (index in obj_list) {
if (obj_list[index][key] === value) return index;
}
return -1;
}
// Find the string in the list (default -1)
var test1 = indexOfbyKey(object_list, 'name', 'Stevie');
var test2 = indexOfbyKey(object_list, 'last_name', 'some other name');

这取决于什么对你来说是重要的。使用一行代码可能会节省代码行数,或者将一个通用的解决方案放在覆盖各种边缘情况的某个地方是非常聪明的。但有时最好直接说:“这里我是这样做的”,而不是让未来的开发人员做额外的逆向工程工作。特别是如果你认为自己是“新手”,就像你的问题一样。

这里的大多数回答不能解决所有情况。 我发现这个解决方案更好:

const isInarray = myArr.filter((obj) => obj.hello === 'stevie' && obj.foo === 'baz').length > 0;
if (!isInArray) {
....
}

你可以使用findIndex ()方法:

cosnt myIndex=myArray.findIndex(el=>el.hello==='stevie')

if myIndex <0表示不存在