对象数组中的indexOf方法?

时间:2011-12-29 12:59:01

标签: javascript

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

想象一下这种情况:

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

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

现在我希望indexOf hello属性为'stevie'的对象,在此示例中为1

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

28 个答案:

答案 0 :(得分:884)

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

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

答案 1 :(得分:317)

除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. 不要在数组循环中使用...
  2. 一旦找到“针头”,一定要突破循环或退出功能
  3. 小心对象平等
  4. 例如,

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

答案 2 :(得分:107)

在ES2015中,这很简单:

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

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

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

答案 3 :(得分:25)

var idx = myArray.reduce( function( cur, val, index ){

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

}, -1 );

答案 4 :(得分:18)

我喜欢Pablo的回答,但是Array#indexOf和Array #map并不适用于所有浏览器。如果可用,Underscore将使用本机代码,但也会有后备。此外,它还具有完全符合Pablo匿名地图方法的方法。

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

答案 5 :(得分:15)

或原型:

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

答案 6 :(得分:9)

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

答案 7 :(得分:6)

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

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

答案 8 :(得分:5)

我比较了几种方法,并以最快的方式解决了这个问题。这是一个for循环。它比任何其他方法快5倍。

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

答案 9 :(得分:4)

array.filter(function(item, indx, arr){ return(item.hello === 'stevie'); })[0];

注意[0]

reduce的答案中使用Antonio Laguna是合适的。

道歉......

答案 10 :(得分:3)

如果您只想找到位置,请参阅@Pablo's answer

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

答案 11 :(得分:3)

虽然这里的大多数其他答案都是有效的。有时,最好只在您将使用它的地方附近做一个简单的简单功能。

// 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');

这取决于对您来说重要的事情。它可以节省代码行,并且非常聪明地使用单行程序,或者在一个覆盖各种边缘情况的地方放置通用解决方案。但有时候只是说:“#34;在这里,我就这样做了#34;而不是让未来的开发人员进行额外的逆向工程工作。特别是如果你认为自己是一个新手&#34;喜欢你的问题。

答案 12 :(得分:3)

简单:

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

答案 13 :(得分:3)

试试这个:

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

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

答案 14 :(得分:2)

使用ES6 findIndex method,不使用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];
    });
  });
}

(来自我对this dupe的回答)

答案 15 :(得分:2)

如果您的对象与您在数组中使用的对象相同,则您应该能够像使用字符串一样获取Object的索引。

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

答案 16 :(得分:2)

您基本上可以使用原生且方便的功能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);

答案 17 :(得分:2)

@Monika Garg answer的使用者,您可以使用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);

答案 18 :(得分:2)

使用underscore.js library

中的_.findIndex

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

答案 19 :(得分:2)

我已经制作了一个通用函数来检查下面的代码&amp;适用于任何对象

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(表示未找到匹配)&amp;第二个警报将返回0(表示匹配找到)。

答案 20 :(得分:2)

请参阅此示例:http://jsfiddle.net/89C54/

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

它开始计为零。

答案 21 :(得分:1)

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

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

答案 22 :(得分:0)

您只需使用

即可

&#13;
&#13;
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);
&#13;
&#13;
&#13;

没有下划线,没有,只是减少。

答案 23 :(得分:0)

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

答案 24 :(得分:0)

此处的大多数回答都无法解决所有情况。 我发现这个解决方案更好:

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

答案 25 :(得分:-1)

这没有自定义代码

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
  

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

答案 26 :(得分:-1)

您可以创建自己的原型来执行此操作:

类似的东西:

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

答案 27 :(得分:-2)

我更愿意使用findIndex()方法:

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

index会为您提供索引编号。