对象数组中的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
只是一些说明:
- 不要在数组中使用for …循环
- 一旦找到你的“针”,一定要跳出循环或退出功能
- 小心对象平等
例如,
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
会给你索引号。