15

I'm looking at some jQuery code I'm writing at the moment and it just looks plain weird to my C# brain. Is there a better way of doing this?

var idToLookFor = 2;
var myArray = [{id:1},{id:2},{id:3}]

var arrayItem = $.grep(myArray , function (elm) {
    return elm.id == idToLookFor;
});

var itemFound = arrayItem[0];

I can understand grep returning an array as rather than it being a find type function its a filter type function so I guess the question should really be is there a function that will only return one item rather than an array?

NDM
  • 6,731
  • 3
  • 39
  • 52
Jammer
  • 9,969
  • 11
  • 68
  • 115
  • 4
    Yes, you're already using it in the last line. – Blazemonger Aug 02 '13 at 13:35
  • If you just need the first occurrence in the array, just [loop over the array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) until you got it? – NDM Aug 02 '13 at 13:39
  • I think it's probably just a typo [in the question] but the above wouldn't work, `myArray` doesn't contain any objects with a property named `Id` – billyonecan Aug 02 '13 at 13:42
  • Yeah, that is a typo :) – Jammer Aug 02 '13 at 13:48
  • 2
    @Jammer, you could just return the element in the `grep`? something like this `var arrayItem = $.grep(myArray , function (elm) { if(elm.id == idToLookFor) return elm; });`. Which will return an empty array if it doesn't match anything – Henrik Andersson Aug 02 '13 at 14:03
  • underscore.js has a find function that does exactly what you need. `http://underscorejs.org/` – Pierre Sep 19 '14 at 19:07
  • Why overcomplicate it? Just use what's mentioned here: https://stackoverflow.com/questions/7364150/find-object-by-id-in-an-array-of-javascript-objects – Bonez024 May 17 '23 at 19:16

6 Answers6

14

This answer to another question points out that grep will continue looping over the array even after it has found the right answer. Not an issue in the above example but if your array could be much larger it's worth noting: non grep solution

It's just a for loop that is wrapped in a function that returns the object it finds. Even if you stick with the grep method I'd still abstract your logic into some reusable function and keep it in a nice helper file somewhere.

I'm posting a modified version of the answer purely so you can see what I mean before deciding if you want to follow the link:

for (var i = 0, len = myArray.length; i < len; i++) 
{
    if (myArray[i].id === idToLookFor)
    {
        return myArray[i]; // Return as soon as the object is found
    }
}
Community
  • 1
  • 1
lewis
  • 253
  • 1
  • 9
3

Well, if you like using jQuery generic function style, you could add something like this in your personal library:

$.extend( {
    findFirst: function( elems, validateCb ){
        var i;
        for( i=0 ; i < elems.length ; ++i ) {
            if( validateCb( elems[i], i ) )
                return elems[i];
        }
        return undefined;
    }
} );

Usage for your example:

var result = $.findFirst( myArray, function(elm) {
    return elm.id == idToLookFor;
});

Of course, you could instead use your own namespace...

I assume your concern is with code readability. I think using directly a language loop solution for this matter is also quite fine.

You could also be concerned with waste, as there is no need to maintain another array structure just for this, but at least for your example it seems like a micro-optimisation issue.

José Andias
  • 1,894
  • 2
  • 29
  • 31
0

If you have an array of Objects, this would do:

var result = myArray.filter(function(v) {
    return v.id === idToLookFor; 
})[0];

For a simple array You could use inArray .It returns the key of the array where the item is present!.

var itemFound= myArray[$.inArray(idToLookFor,myArray)];

Aditya
  • 4,453
  • 3
  • 28
  • 39
  • This only works with array of values. The array in the question is an array of objects. – Didier Ghys Aug 02 '13 at 13:47
  • 3
    why would you filter the whole array, if you just need the first occurrence? for-loop is faster and better – NDM Aug 02 '13 at 14:01
0

Expanding on Blazemonger's comment:

var itemFound = myArray[idToLookFor - 1]

should get you the item you're looking for if I understand your question correctly. Note the -1 to account for indexing from 1

EDIT: this also assumes that the array will always be sorted in ascending order by ID as it is in your question. If your id's do increment nicely but the array is not initially sorted by them see: Sort array of objects by string property value in JavaScript

Community
  • 1
  • 1
underbar
  • 588
  • 3
  • 15
  • 1
    That's a nice solution if the items are indeed sorted. – Jammer Aug 02 '13 at 13:49
  • 3
    I don't think the array items "id" property has anything to do with the index in the array. What Blazemonger was saying is that to get the first element in an array, just use `[0]`, that's all. – Didier Ghys Aug 02 '13 at 13:49
  • Ahh I see, I just thought that the id's started at 1 and incremented by one, and were not just an arbitrary number. If that was the case then the array could be sorted on by the id value before using my solution. http://stackoverflow.com/questions/1129216/sorting-objects-in-an-array-by-a-field-value-in-javascript – underbar Aug 02 '13 at 13:55
0

Please use

var idToLookFor = 2;
var myArray = [{id:1},{id:2},{id:3}]

var arrayItem = $.map(myArray , function (elm) {
    if(elm.id == idToLookFor)
      return elm.id ;
});

var itemFound = arrayItem[0];
0

check my answer here

Copied from polyfill Array.prototype.find code of Array.find, and added the array as first parameter.

you can pass the search term as predicate function

Abou-Emish
  • 2,201
  • 1
  • 22
  • 22