对象数组中的indexOf方法?

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

想象一下这个场景:

var hello = { hello: 'world', foo: 'bar' }; var qaz = { hello: 'stevie', foo: 'baz' } var myArray = []; myArray.push(hello,qaz); 

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

我是JavaScript的新手,我不知道是否有一个简单的方法,或者如果我应该建立自己的功能来做到这一点。

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

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

与地图的解决方案是好的。 但是每次搜索都迭代整个数组。 这只是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 

只是一些说明:

  1. 不要在数组中使用for …循环
  2. 一旦找到你的“针”,一定要跳出循环或退出功能
  3. 小心对象平等

例如,

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

我想你可以使用'map'函数在一行中解决它:

 pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie'); 

在ES2015中,这很简单:

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

或者,对于较大的阵列可能会有更好的性能:

 myArray.findIndex(x => x.hello === 'stevie') 
 var idx = myArray.reduce( function( cur, val, index ){ if( val.hello === "stevie" && cur === -1 ) { return index; } return cur; }, -1 ); 

我喜欢Pablo的回答,但Array#indexOf和Array#map在所有浏览器上都不起作用。 如果可用,Underscore将使用本机代码,但也有后备功能。 再加上它采用了Pablo的匿名地图方法所采用的pluck方法。

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

或者原型吧:

 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"); 

简要

 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); } }; 
 array.filter(function(item, indx, arr){ return(item.hello === 'stevie'); })[0]; 

注意[0]

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

道歉为简洁…

简单:

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

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

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

它开始以零计数。

我做了一个通用的函数来检查下面是代码和作品的任何对象

 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(意味着找到匹配)。

使用underscore.js库中的 _.findIndex

以下是示例_.findIndex([{a:1},{a: 2,c:10},{a: 3}], {a:2,c:10}) //1

尝试这个:

 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()

如果数组中的元素满足提供的测试函数,则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); 

@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); 

如果你只想找到位置,请参阅@Pablo的答案 。

pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');

然而,如果您期待找到元素 (即如果您正在考虑像myArray[pos] ),那么使用filter就有更高效的单线方法。

element = myArray.filter((e) => e.hello === 'stevie')[0];

查看性能结果(〜42%ops / sec): http : //jsbench.github.io/#7fa01f89a5dc5cc3bee79abfde80cdb3

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

  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; } } 

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

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

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

如果您的实现尚未提供findIndex (大多数不),则可以添加一个支持此搜索的轻型polyfill:

 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]; }); }); } 

(从我在这个愚蠢的答案)

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

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"); 

你可以简单地使用

 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); 
 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")); 

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

就像是:

 Array.prototype.indexOfObject = function (object) { for (var i = 0; i < this.length; i++) { if (JSON.stringify(this[i]) === JSON.stringify(object)) return i; } } 

这工作没有自定义代码

 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 

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

我宁愿使用findIndex()方法:

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

index会给你索引号。