3

Is there any short and neat way of finding an item in the following list with the given searchObject specifications?

var list = [
    { id:1, name: "foo", description: "description 1" },
    { id:2, name: "bar", description: "description 2" },
    { id:3, name: "baz", description: "description 3" },
];

var searchObject = { id: 2, name: "bar" };

The searchObject does NOT necessarily have all the properties of an item in the list. I need the operator between properties to be AND (id==2 && name=="bar"). The following is what I have come up with. Is there anything native in javascript that can do this?

for (var i in list) {
    var found = true;
    for (var p in searchObject) {
        if (list[i][p] !== searchObject[p]) {
            found = false;
            break;
        }
    }
    if(found) return list[i];
}
hamid
  • 51
  • 3
  • Please do not use `for (x in y)` on arrays. [It does NOT do what you think](http://stackoverflow.com/a/500531/36866) – some Nov 10 '13 at 02:22

2 Answers2

3

No, there's not a native way. Some people might like the following better because its more javascripty, but it certainly doesn't have the superb browser support that your original version has.

var matches = list.filter(function(arrElem){
    return Object.keys(searchObject).every(function(prop){
        return searchObject[prop] === arrElem[prop];
    });
});

Note that this returns an array with all matches, not just the first match like yours. Also note that unlike yours, this doesn't test for inherited enumerable properties on the searchObject, although you probably don't want to search for inherited properties.

ps, many of these "I wish js had a nicer way of doing X" desires are satisfied by underscore.js. In particular, the findWhere method is what you're after:

var match = _.findWhere(list, searchObject);
goat
  • 31,486
  • 7
  • 73
  • 96
0

From my experience if the solution ever exists, it will not be much better than yours.

It is better to not use the for...in statement for arrays, because it enumerates properties of the array, not the elements. Consider the following:

Array.prototype.test = function () { };
for (var i in q) console.log(i);

This code will output test which is probably not what you may expect.

Anyway, for this kind of things I use lo-dash. Its _.find(...) method does exactly what you need and you may look at this method's source code, which I presume is most effective realization.

Alex Netkachov
  • 13,172
  • 6
  • 53
  • 85