In an array of objects, fastest way to find the index of an object whose attributes match a search

JavascriptArraysIndexof

Javascript Problem Overview


I've been surfing around a little trying to find an efficient way to do this, but have gotten nowhere. I have an array of objects that looks like this:

array[i].id = some number;
array[i].name = some name;

What I want to do is to find the INDEXES of the objects where id is equal to, for example, one of 0,1,2,3 or 4. I suppose I could just do something like :

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

While this would work, it looks to be quite expensive and slow (not to mention ugly), especially if array.length could be large. Any ideas on how to spruce this up a bit? I thought of using array.indexOf somehow but I don't see how to force the syntax. This

array.indexOf(this.id === 0);

for example, returns undefined, as it probably should.

Javascript Solutions


Solution 1 - Javascript

Maybe you would like to use higher-order functions such as "map". Assuming you want search by 'field' attribute:

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

Solution 2 - Javascript

The simplest and easiest way to find element index in array.

ES5 syntax: [{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

ES6 syntax: [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)

Solution 3 - Javascript

The new Array method .filter() would work well for this:

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery can also do this with .grep()

edit: it is worth mentioning that both of these functions just iterate under the hood, there won't be a noticeable performance difference between them and rolling your own filter function, but why re-invent the wheel.

Solution 4 - Javascript

If you care about performance, dont go with find or filter or map or any of the above discussed methods

Here is an example demonstrating the fastest method. HERE is the link to the actual test

Setup block

var items = []

for(var i = 0; i < 1000; i++) {
    items.push({id: i + 1})
}

var find = 523

Fastest Method

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

Slower Methods

items.findIndex(item => item.id === find)

SLOWEST method

items.map(item => item.id).indexOf(find);

Solution 5 - Javascript

Since there's no answer using regular array find:

var one = {id: 1, name: 'one'};
var two = {id: 2, name:'two'}
var arr = [one, two] 

var found = arr.find((a) => a.id === 2)

found === two // true

arr.indexOf(found) // 1

Solution 6 - Javascript

array.forEach(function (elem, i) {  // iterate over all elements of array
    indexes[elem.id] = i;           // take the found id as index for the
});                                 // indexes array and assign i

the result is a look up list for the id. with the given id we get the index of the record.

Solution 7 - Javascript

var indices = [];
var IDs = [0, 1, 2, 3, 4];

for(var i = 0, len = array.length; i < len; i++) {
    for(var j = 0; j < IDs.length; j++) {
        if(array[i].id == ID) indices.push(i);
    }
}

Solution 8 - Javascript

const index = array.findIndex(item => item.id === 'your-id');

This should get you the index of item in array with id === your-id

array = [ {id:1}, {id:2} ];

const index = array.findIndex(item => item.id === 2);

console.log(index);

Solution 9 - Javascript

A new way using ES6

let picked_element = array.filter(element => element.id === 0);

Solution 10 - Javascript

Using the ES6 map function:

let idToFind = 3;
let index = someArray.map(obj => obj.id).indexOf(idToFind);

Solution 11 - Javascript

Sounds to me like you could create a simple iterator with a callback for testing. Like so:

function findElements(array, predicate)
{
    var matchingIndices = [];

    for(var j = 0; j < array.length; j++)
    {
        if(predicate(array[j]))
           matchingIndices.push(j);
    }

    return matchingIndices;
}

Then you could invoke like so:

var someArray = [
     { id: 1, text: "Hello" },
     { id: 2, text: "World" },
     { id: 3, text: "Sup" },
     { id: 4, text: "Dawg" }
  ];

var matchingIndices = findElements(someArray, function(item)
   {
        return item.id % 2 == 0;
   });

// Should have an array of [1, 3] as the indexes that matched

Solution 12 - Javascript

Adapting Tejs's answer for mongoDB and Robomongo I changed

matchingIndices.push(j);

to

matchingIndices.push(NumberInt(j+1));

Solution 13 - Javascript

To summary all of the great answer above and additional of my answer regarding find all the indexes occurred from some of the comment.

  1. To return the index of the first occurrence.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }];
const idYourAreLookingFor = 2;

//ES5 
//Output: 1
array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor);

//ES6 
//Output: 1
array.findIndex(obj => obj.id === idYourAreLookingFor);

  1. To return the index array of all occurrences, using reduce.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }]
const idYourAreLookingFor = 2;

//ES5
//Output: [1, 4]
array.reduce(function (acc, obj, i) {
  if (obj.id === idYourAreLookingFor)
    acc.push(i);
  return acc;
}, []);

//ES6
//Output: [1, 4]
array.reduce((acc, obj, i) => (obj.id === idYourAreLookingFor) ? acc.concat(i) : acc, [])

Solution 14 - Javascript

I've created a tiny utility called super-array where you can access items in an array by a unique identifier with O(1) complexity. Example:

const SuperArray = require('super-array');

const myArray = new SuperArray([
  {id: 'ab1', name: 'John'},
  {id: 'ab2', name: 'Peter'},
]);

console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'}
console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'}

Solution 15 - Javascript

Sometimes the old ways are the best, as noted by @PirateBay.

With ES 6/7 ".find" is very fast too & stops when it matches (unlike .map or .filter)

items.find(e => e.id === find)?.id

Solution 16 - Javascript

As I can't comment yet, I want to show the solution I used based on the method Umair Ahmed posted, but when you want to search for a key instead of a value:

[{"a":true}, {"f":true}, {"g":false}]
.findIndex(function(element){return Object.keys(element)[0] == "g"});

I understand that it doesn't answer the expanded question, but the title doesn't specify what was wanted from each object, so I want to humbly share this to save headaches to others in the future, while I undestart it may not be the fastest solution.

Solution 17 - Javascript

var test = [
  {id:1, test: 1},
  {id:2, test: 2},
  {id:2, test: 2}
];

var result = test.findIndex(findIndex, '2');

console.log(result);

function findIndex(object) {
  return object.id == this;
}

will return index 1 (Works only in ES 2016)

Solution 18 - Javascript

I like this method because it's easy to compare to any value in the object no matter how deep it's nested.

 while(i<myArray.length && myArray[i].data.value!==value){
  i++; 
}
// i now hows the index value for the match. 
 console.log("Index ->",i );

Solution 19 - Javascript

One simple method to find index of object in an array based on a specific match.

//list of bookings
const bookings = [
    { status: "accepted", _id: "6055cadd062eb5153c089121", title: "This is test title", user: "id", team: "id" },
    { status: "pending", _id: "6055cb33062eb5153c089122", title: "title1", description: "test description", user: "id", team: "id" },
    { status: "accepted", _id: "6055cb3d062eb5153c089123", title: "title2", description: "test description", user: "id", team: "id" }
]

//return index of the element if find else return -1 
const findIndex = (booking) => bookings.findIndex((b, index) => {
    if (b._id === booking._id) return true
})

//test 1
let booking = { status: "pending", _id: "6055cb33062eb5153c089122", title: "title2", description: "test description", user: "id", team: "id" }
console.log("index >>> ", findIndex(booking))
//output : 1

//test 2
booking = { status: "rejected", _id: "6055cb33062eb5153c089198", title: "title3", description: "test description", user: "id", team: "id" }
console.log("index >>> ", findIndex(booking))
//output : -1

//test 3
const id = '6055cb3d062eb5153c089123'
console.log("index >>> ", findIndex({ _id: id }))
//output : 2

find-searchElementInArrayObObjects

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPetrovView Question on Stackoverflow
Solution 1 - JavascriptPablo Francisco Pérez HidalgoView Answer on Stackoverflow
Solution 2 - JavascriptUmair AhmedView Answer on Stackoverflow
Solution 3 - JavascriptjbabeyView Answer on Stackoverflow
Solution 4 - JavascriptPirateAppView Answer on Stackoverflow
Solution 5 - JavascriptenapupeView Answer on Stackoverflow
Solution 6 - JavascriptNina ScholzView Answer on Stackoverflow
Solution 7 - JavascriptElliot BonnevilleView Answer on Stackoverflow
Solution 8 - JavascriptPulpDoodView Answer on Stackoverflow
Solution 9 - JavascriptSilve2611View Answer on Stackoverflow
Solution 10 - JavascriptJoeTideeView Answer on Stackoverflow
Solution 11 - JavascriptTejsView Answer on Stackoverflow
Solution 12 - Javascriptuser2584621View Answer on Stackoverflow
Solution 13 - Javascripttrungk18View Answer on Stackoverflow
Solution 14 - JavascriptpatotomaView Answer on Stackoverflow
Solution 15 - JavascriptSarahJView Answer on Stackoverflow
Solution 16 - JavascriptXander NView Answer on Stackoverflow
Solution 17 - JavascripteXtremeView Answer on Stackoverflow
Solution 18 - JavascriptDaniel LefebvreView Answer on Stackoverflow
Solution 19 - JavascriptKhattak01View Answer on Stackoverflow