Monday, May 24, 2010

JavaScript: Search an Array of Objects

The Object of your Desire

Ajax aficionados often find themselves with heaps of Json data, often arrays of data, fresh from the server, which they then magic into Html client-side.

A number of options exist for searching for a specific item in an array:

But what if you have an array of objects?

You can use JavaScript’s built-in indexOf(obj) method for arrays to compare for object identity:

arr.indexOf(obj);

But this requires the entire hotly-sought object and, apparently, this may not work in some browsers, such as IE6, without a creative work-around.

A Generic (and Perhaps Obvious) Solution

Recently, I wrote the following function:

function ArrayIndexOf(a, fnc) {
if (!fnc || typeof (fnc) != 'function') {
return -1;
}
if (!a || !a.length || a.length < 1) return -1;
for (var i = 0; i < a.length; i++) {
if (fnc(a[i])) return i;
}
return -1;
}

ArrayIndexOf(a, fnc) takes two parameters:

  • the array
  • a function of signature: bool f(item) {}

ArrayIndexOf compares each array item with, well, whatever you want, and returns the index of the item in the array, or -1 if there is no match. This approach gives you the flexibility to search for whatever specific field, or fields, you desire.

Sample usage:

var i = ArrayIndexOf(arrMovies, function(obj) {
return obj.MovieTitle == 'The Matrix';
});
if (-1 != i) {
alert('Found it! (Psst: take the blue pill!)');
}

Disclaimer:

  • I haven’t tested this code for performance, so if your arrays are immense, test it out
  • Handle with care. JavaScript’s type-insensitivity means you better be sure the object properties you test against exist if you don’t want to crash and burn.

6 comments:

Harry said...

brilliant - been looking all over the place for something like this! thank you!

Karthikeyan Mohan said...

The following code is generic and can handle the scenario where the property is not present.

function aIndexOf(a, fnc) {
if (!fnc || typeof (fnc) != 'function') {
return -1;
}
if (!a || !a.length || a.length < 1) return -1;
for (var i = 0; i < a.length; i++) {
if (fnc(a[i])) return i;
}
return -1;
}

function arrayIndexOf(a, f, v)
{
var i = aIndexOf(a, function(obj) {
if(obj[f] != undefined)
{
return obj[f] == v;
}
else
{
return false;
}
});
return i;
}

Daniel said...

Thanks, Karthikeyan.

That is a useful extension of the idea. :)

david said...

http://api.jquery.com/jQuery.grep/

Daniel said...

Thanks for that, david.

Note that grep updates the original array.

Michael-Rainabba Richardson said...

David: Maybe I missed something but,

$.grep() = "The original array is not affected."

http://api.jquery.com/jQuery.grep/