Как найти индекс объекта внутри массива, используя underscore.js?

Я хочу получить индекс данного значения внутри массива, используя underscore.js.

Вот мой случай

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

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

Я использовал следующий код,

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

Также пробовал это тоже

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

Но это returns -1. Поскольку он не входит в эту функцию. Поэтому я не получил это сообщение.

Что не так с моим кодом. Может кто-нибудь мне помочь?

Ответ 1

Используйте это вместо:

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

В вашем фрагменте data === searchValue сравниваются ссылки объектов, вы не хотите этого делать. С другой стороны, если вы используете data == searchValue, вы собираетесь сравнивать представления строк объектов, т.е. [Object object], если у вас нет переопределенных методов toString.

Таким образом, правильный способ сравнения объектов - использовать _.isEqual.

Ответ 2

Я бы очень хотел взглянуть на lodash. Он содержит довольно много отличных функций, которых, к сожалению, не хватает.

Например, это то, что вы сделали бы с 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

Кроме того, если вы обязаны использовать Underscore, вы можете захватить сборку lodash underscore в https://raw.github.com/lodash/lodash/2.4.1/dist/lodash.underscore.js


ES2015

Теперь, когда ES2015 широко используется (через транспилеры, такие как Babel), вы можете отказаться от lodash и подчеркивания для этой задачи и использовать собственные методы:

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

arr.findIndex(i => i.id === 1); // 0

Ответ 3

Возможно, мое предложение даст вам совет.

Почему вы используете обратный вызов для метода indexof? Подпись индекса в underscore.js следующая:

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

find может быть лучше для этой задачи:

_.find(array, function(item, index) {
  if (item.id == searchValue.id) {
    alert(index);
  }
});

Ответ 4

С объектами, === и == проверьте, ссылаются ли две ссылки на объект тот же; он не проверяет эквивалентные объекты:

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

Вы должны проверить свойства объекта, чтобы принять решение. В вашем случае свойство id выглядит как хорошая опция или если вы хотите сравнить все свойства, вы можете использовать Underscore isEqual.

Ответ 5

Подчеркивание использует собственный метод indexOf, если он доступен, иначе применяется резервное копирование. Таким образом, для списка объектов вы должны реализовать его каким-либо другим способом.

Одним из примеров может быть

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

или

_.map(array,function(e) { return e.key; }).indexOf(value);

Ответ 6

_.find(array, function(item, index) {
  if (item.id == searchValue.id) {
    alert(index);
  }
});

Ответ 7

Если у вас есть сложные объекты и вы хотите найти один объект в коллекции, ищущий определенное свойство, просто перейдите по ссылке:

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

Где "arrayObj" - это коллекция с объектами, "id" - это prop, а "1" - это значение, находящееся в поиске.