admin管理员组

文章数量:1125630

How can I simply and directly find the index within an array of objects meeting some condition?

For example, given this input:

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

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

How can I search myArray to find the index of the element whose hello property equals 'stevie' (in this case, the result should be 1)?

How can I simply and directly find the index within an array of objects meeting some condition?

For example, given this input:

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

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

How can I search myArray to find the index of the element whose hello property equals 'stevie' (in this case, the result should be 1)?

Share Improve this question edited Mar 28, 2023 at 12:28 surfmuggle 5,9168 gold badges55 silver badges89 bronze badges asked Dec 29, 2011 at 12:59 Antonio LagunaAntonio Laguna 9,2627 gold badges37 silver badges72 bronze badges 5
  • 1 Do you want to merge the two objects hello and qaz? – Armin Commented Dec 29, 2011 at 13:01
  • Nope I don't. I want to have a list of objects in an array. – Antonio Laguna Commented Dec 29, 2011 at 13:05
  • Ah okay! You want to know the position of the whole object in the array, which has a defined property. – Armin Commented Dec 29, 2011 at 13:06
  • 13 I found a very simple function to solve this exact problem with this SO answer: var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor); var objectFound = array[elementPos]; [link] (stackoverflow.com/a/16100446/1937255) – Rick Commented Jul 30, 2015 at 0:21
  • 1 ES6 Array.indexOf is better than accepted answer (if ES6 works for you) - see full example below – yar1 Commented Jan 31, 2017 at 6:44
Add a comment  | 

29 Answers 29

Reset to default 1386

I think you can solve it in one line using the map function:

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

Array.prototype.findIndex is supported in all browsers other than IE (non-edge). But the polyfill provided is nice.

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

The solution with map is okay. But you are iterating over the entire array every search. That is only the worst case for findIndex which stops iterating once a match is found.


There's not really a concise way (when devs had to worry about IE8), but here's a common solution:

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

or as a function:

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

Just some notes:

  1. Don't use for...in loops on arrays
  2. Be sure to break out of the loop or return out of the function once you've found your "needle"
  3. Be careful with object equality

For example,

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

In ES2015, this is pretty easy:

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

or, probably with better performance for larger arrays:

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

I like Pablo's answer, but Array#indexOf and Array#map don't work on all browsers. Underscore will use native code if it's available, but has fallbacks as well. Plus it has the pluck method for doing exactly what Pablo's anonymous map method does.

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

Or prototype it :

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

While, most other answers here are valid. Sometimes, it's best to just make a short simple function near where you will use it.

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

It depends on what is important to you. It might save lines of code and be very clever to use a one-liner, or to put a generic solution somewhere that covers various edge cases. But sometimes it's better to just say: "here I did it like this" rather than leave future developers to have extra reverse engineering work. Especially if you consider yourself "a newbie" like in your question.

If your object is the same object of the ones you are using within the array, you should be able to get the index of the Object in the same way you do as if it was a string.

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

I compared several methods and received a result with the fastest way to solve this problem. It's a for loop. It's 5+ times faster than any other method.

Here is the test's page: https://jsbench.me/9hjewv6a98

you can use findIndex() method:

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

if myIndex < 0 that means is not exist

Brief

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

Use Cases :

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

I did some performance testing of various answers here, which anyone can run them self:

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

Based on my initial tests in Chrome, the following method (using a for loop set up inside a prototype) is the fastest:

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

This code is a slightly modified version of Nathan Zaetta's answer.

In the performance benchmarks I tried it with both the target being in the middle (index 500) and very end (index 999) of a 1000 object array, and even if I put the target in as the very last item in the array (meaning that it it has to loop through every single item in the array before it's found) it still ends up the fastest.

This solution also has the benefit of being one of the most terse for repeatedly executing, since only the last line needs to be repeated:

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

Mind the [0].

It is proper to use reduce as in Antonio Laguna's answer.

Apologies for the brevity...

Try this:

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

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

simple:

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

You can use a native and convenient function Array.prototype.findIndex() basically:

The findIndex() method returns an index in the array, if an element in the array satisfies the provided testing function. Otherwise -1 is returned.

Just a note it is not supported on Internet Explorer, Opera and Safari, but you can use a Polyfill provided in the link below.

More information:

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

If you are only interested into finding the position see @Pablo's answer.

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

However, if you are looking forward to finding the element (i.e. if you were thinking of doing something like this myArray[pos]), there is a more efficient one-line way to do it, using filter.

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

See perfomance results (~ +42% ops/sec): http://jsbench.github.io/#7fa01f89a5dc5cc3bee79abfde80cdb3

See this example: http://jsfiddle.net/89C54/

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

It starts to count with zero.

I have made a generic function to check the below is the code & works for any object

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

The first alert will return -1 (means match not found) & second alert will return 0 (means match found).

Use _.findIndex from underscore.js library

Here's the example _.findIndex([{a:1},{a: 2,c:10},{a: 3}], {a:2,c:10}) //1

Using the ES6 findIndex method, without lodash or any other libraries, you can write:

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

This will compare the immediate properties of the object, but not recurse into the properties.

If your implementation doesn't provide findIndex yet (most don't), you can add a light polyfill that supports this search:

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

(from my answer on this dupe)

Furthor of @Monika Garg answer, you can use findIndex() (There is a polyfill for unsupprted browsers).

I saw that people downvoted this answer, and I hope that they did this because of the wrong syntax, because on my opinion, this is the most elegant way.

The findIndex() method returns an index in the array, if an element in the array satisfies the provided testing function. Otherwise -1 is returned.

For example:

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

This is the way to find the object's index in array

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

This works without custom code

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

Note: this does not give the actual index, it only tells if your object exists in the current data structure

You can simply use

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

No underscore, no for, just a reduce.

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

Most answers response here do not resolve all cases. I found this solution better:

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

You can create your own prototype to do this:

something like:

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

I will prefer to use findIndex() method:

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

index will give you the index number.

本文标签: javascriptindexOf method in an object arrayStack Overflow