How can I find the index of an object inside a Array using underscore.js?
Asked Answered
M

8

10

I want to get the index of the given value inside a Array using underscore.js.

Here is my case

var array = [{'id': 1, 'name': 'xxx'},
             {'id': 2, 'name': 'yyy'},
             {'id': 3, 'name': 'zzz'}];

var searchValue = {'id': 1, 'name': 'xxx'};

I used the following code,

var index = _.indexOf(array, function(data) { 
                alert(data.toSource()); //For testing purpose 
                return data === searchValue; 
            });

Also tried this too

var index = _.indexOf(array, {id: searchValue.id});

But it returns -1 . Since it does not enter into that function. So I didn't get that alert message.

Whats wrong with my code. Can anyone help me?

Merril answered 3/2, 2014 at 8:3 Comment(0)
W
14

Use this instead:

var array = [{'id': 1, 'name': 'xxx'},
             {'id': 2, 'name': 'yyy'},
             {'id': 3, 'name': 'zzz'}];

var searchValue = {'id': 1, 'name': 'xxx'},
    index = -1;

_.each(array, function(data, idx) { 
   if (_.isEqual(data, searchValue)) {
      index = idx;
      return;
   }
});

console.log(index); //0

In your snippet data === searchValue compares the objects' references, you don't want to do this. On the other hand, if you use data == searchValue you are going to compare objects' string representations i.e. [Object object] if you don't have redefined toString methods.

So the correct way to compare the objects is to use _.isEqual.

Woof answered 3/2, 2014 at 8:5 Comment(2)
@T.J.Crowder yep, agree. Fixed my answer.Woof
You might want to review how isEqual is used. :-)Arvid
A
16

I'd strongly suggest taking a look at lodash. It contains quite a bit of nifty little functions that unfortunately underscore is lacking.

For example, this is what you would do with lodash:

var array = [{'id': 1, 'name': 'xxx'},
           {'id': 2, 'name': 'yyy'},
           {'id': 3, 'name': 'zzz'}];

var searchValue = {'id': 1, 'name': 'xxx'};


var index = _.findIndex(array, searchValue); 
console.log(index === 0); //-> true

http://lodash.com/docs#findIndex

Also, if you're bound to using Underscore - you can grab lodash's underscore build at https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js


ES2015

With ES2015 now in wide use (through transpilers like Babel), you could forego lodash and underscore for the task at hand and use native methods:

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

arr.findIndex(i => i.id === 1); // 0
Antoineantoinetta answered 3/2, 2014 at 9:20 Comment(0)
W
14

Use this instead:

var array = [{'id': 1, 'name': 'xxx'},
             {'id': 2, 'name': 'yyy'},
             {'id': 3, 'name': 'zzz'}];

var searchValue = {'id': 1, 'name': 'xxx'},
    index = -1;

_.each(array, function(data, idx) { 
   if (_.isEqual(data, searchValue)) {
      index = idx;
      return;
   }
});

console.log(index); //0

In your snippet data === searchValue compares the objects' references, you don't want to do this. On the other hand, if you use data == searchValue you are going to compare objects' string representations i.e. [Object object] if you don't have redefined toString methods.

So the correct way to compare the objects is to use _.isEqual.

Woof answered 3/2, 2014 at 8:5 Comment(2)
@T.J.Crowder yep, agree. Fixed my answer.Woof
You might want to review how isEqual is used. :-)Arvid
C
3

May be my suggestion will give you advice.

Why do you use callback for indexof method? The signature of indexof in underscore.js is the following:

_.indexOf(array, value, [isSorted]) 

find could be better for this task:

_.find(array, function(item, index) {
  if (item.id == searchValue.id) {
    alert(index);
  }
});
Confrere answered 3/2, 2014 at 8:22 Comment(1)
Interesting. The documentation of Underscore is lacking there, as they don't explain what are the arguments of the predicates (they only show examples with the value).Nimitz
A
2

With objects, === and == check to see if two references refer to the same object; it doesn't check for equivalent objects:

var a = {foo: "bar"};
var b = {foo: "bar"};
console.log(a === b); // false, `a` and `b` refer to different (but equivalent) objects
a = b = {something: "here"};
console.log(a === b); // true, `a` and `b` refer to the *same* object

You have to test the object's properties to make the decision. In your case, the id property looks like a good option, or if you want to compare all of the properties, you might use Underscore's isEqual.

Arvid answered 3/2, 2014 at 8:5 Comment(0)
N
2

Underscore uses native indexOf method if available,else applies fallback. Thus, for a list of objects you have to implement it in some other way.

One example could be

_.chain(array).pluck("key").indexOf("value").value();

or

_.map(array,function(e) { return e.key; }).indexOf(value);
Nonunion answered 3/2, 2014 at 8:23 Comment(0)
R
1

In case you have complicated objects, and want to search one object in the collection looking for a certain property, just go with:

 _.indexOf(arrayObj, _.findWhere(arrayObj, {id: 1})  );

Where "arrayObj" is the collection with objects, "id" is the prop, and "1" is the value being in search.

Rutty answered 3/11, 2017 at 12:38 Comment(0)
B
1

i am using find index

 _.findIndex(array, searchValue); 
Behan answered 23/5, 2021 at 20:49 Comment(0)
F
0
_.find(array, function(item, index) {
  if (item.id == searchValue.id) {
    alert(index);
  }
});
Flawed answered 6/8, 2015 at 10:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.