Is the IndexOf method in javascript more efficient than iterating through an array?
Asked Answered
C

2

5

I have an array of JSON objects and I want to find the object with a certain property. I know this may look like a duplicate question, but please continue because I think it's slightly different than the previous questions.

A guy I work with suggested using IndexOf, and that got me thinking. Is there something similar to the $elemMatch feature in mongo? Is there some command that basically says, in pseudo-code, "get me the object with this property from this array"? With the iteration, I feel like the psuedo-code says "look at the first object in this array. If this object has this property, get me this object. If not, look at the second object in this array....."

I understand how to use IndexOf like my friend suggested, but the more I thought about it, I started thinking that the IndexOf method might be fewer lines of code, but doesn't it ultimately have to iterate through the objects in the array to find the index of the one I need? So if I want to do something to the object with this property, and I use the method IndexOf to get the index, I would then refer to the object like myArray[indexFromIndexOfMethod], and then modify it accordingly, correct? So, if javascript is iterating over the array itself to perform the IndexOf method, why don't I just write my own iteration and save a step? Now if the IndexOf method uses a more efficient way of locating the array element than just iterating through and checking each one, then it would make sense for me to use it. Otherwise, it does not make sense to use the IndexOf method if you can achieve the same results with a simple iteration.

Catabasis answered 17/12, 2015 at 13:54 Comment(6)
I need a better explanation of why it "wouldn't make sense" to use indexOf because you can just write your own iteration and duplicate code that's already been written.Watercool
Not sure how not using indexOf will save you anything. With it, you don't have to write the loop, it does the loop for you.Judah
But the action I want to take using the object can happen at the moment that object is located in the array. So if I write my own iteration, I can add all that stuff into the function. If I use IndexOf, javascript will do whatever it does to find the Index of the element I'm looking for, and then when that is completed, I can use the index generated to get that object. So if IndexOf is no more efficient than iteration, I can combine those two steps into one.Catabasis
accessing an array element by index is so fast you would never notice that differenceBedeck
jsperf comes out slightly in favour of indexOf. But as has been stated, this only works because we're comparing to the exact same object. If you were to search for a different, but identical object, based on an identifying property, indexOf would fail, but all other cases would work.Epner
Unrelated, but there are libraries that provide Mongo-like EL (expression language) functionality on JS objects, but I'd be skeptical they'd be as performant because the expose more functionality.Watercool
A
7

Array.prototype.indexOf also just iterates over the array and returns the first index with a matching value. It's the same thing you can do with a loop. It may or may not be slightly faster than a for loop, since indexOf can be implemented in native code and optimised differently than your for loop can, but there's no fundamental difference.

If you often need to access specific values as fast as possible, it's worth indexing them by that value in an object. Meaning, if you want to find a specific object by its property .foo often, do this:

var byFoo = {}
for (var i = 0; i < myArray.length; i++) {
    byFoo[myArray[i].foo] = myArray[i];
}

This then allows you instantaneous access by using byFoo['baz'].

Of course this has the additional overhead of maintaining these indices in multiple copies possibly, but it will speed up the array access by many magnitudes. You need to weigh the pros and cons.

Autostability answered 17/12, 2015 at 14:5 Comment(3)
Thank you great answer. I can tell that you understand exactly what I was asking and I don't feel like anyone else here did. Sometimes it might be better to read a question a couple of times to get a full understanding of it instead of skimming over it quickly and trying to get the first answer down.Catabasis
Well, it would help if the question was more compact and contained a code sample... :-PAutostability
@ChristopherFlint I think everybody understood your question. What we didn't understand is your perception of the "savings" by writing the code inside a loop, breaking out of that loop after the value in question has been found, etc. to replicate indexOf functionality.Watercool
V
1

indexOf won't work on objects if they are real objects, since two objects will be different from eachother even if they have identical property values, so you can't use a real object as the input for indexOf.

It will only work if the JSON is still unparsed strings, then it'll be the most efficient way.

So the solution I tend to use if I have to reference objects directly, is either make a reference that contains the index of each object, or just use a object itsself instead of an array to store the data objects, and have an unique identifier, like the data object's id, as the key.

// This will fail:
var data = [
    {
        'id' : 1,
        'value' : 'myDataForObj1'
    },
    {
        'id' : 2,
        'value' : 'myDataForObj2'
    }
];

data.indexOf({
    'id' : 2,
    'value' : 'myDataForObj2'   
}); // return -1, as in, not found.


// This will work:
var data = [
    '{"id":1,"value":"myDataForObj1"}',
    '{"id":2,"value":"myDataForObj2"}'
];

data.indexOf('{"id":2,"value":"myDataForObj2"}'); // return 1, as in the second element in the array.

// This is what I usually use:
var data = {
    'id1' :     {
        'id' : 1,
        'value' : 'myDataForObj1'
    },
    'id2' : {
        'id' : 2,
        'value' : 'myDataForObj2'
    }
};

data['id2'].value = 'newValue';

You'll have to make some way to reference everything you want to access directly though, so if you want to be able to find any value in any object, a loop will probably be easier to implement for objects with alot of properties.

Hence I've gotten into the habit of always having some 'id' associated with data I have to manipulate. For example, the end user clicks on a row in a table to edit it. I'll make sure the row has a data-attribute that references to the id the data has in the model which will be the same as the id it has in the backend. This kind of design removes the need to iterate over data storage in most cases.

Vitrescent answered 17/12, 2015 at 14:3 Comment(1)
Thank you I appreciate this answer and if I could choose two best answers I would choose yours. Unfortunately the next guy answered my specific question a little better.Catabasis

© 2022 - 2024 — McMap. All rights reserved.