如何使用underscore.js在数组中查找对象的索引?

10

我想使用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});

但它返回-1。因为它没有进入那个函数。所以我没有收到那个警示信息。

我的代码有什么问题。 有人可以帮我吗?

8个回答

16

我强烈建议看一下lodash。它包含了许多非常有用的小函数,而不幸的是underscore没有这些函数。

例如,使用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 构建版本。


ES2015

随着 ES2015 的广泛使用(通过像 Babel 这样的转译器),您可以放弃 lodash 和 underscore,使用本地方法来完成手头的任务:

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

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

14

请使用这个替代:

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


@T.J.Crowder 是的,同意。我已经修正了我的回答。 - Minko Gechev
你可能想要回顾一下如何使用 isEqual。 :-) - T.J. Crowder

3
也许我的建议会给你一些启示。
为什么要在indexOf方法中使用回调函数?underscore.js中的indexOf签名如下:
_.indexOf(array, value, [isSorted]) 

使用find命令或许更适合这个任务:

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

有趣。Underscore 的文档有所欠缺,因为它们没有解释谓词的参数是什么(它们只展示了带有值的例子)。 - PhiLho

2

在使用对象时,=====用于检查两个引用是否指向同一个对象;它不会检查是否为等价的对象:

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


2

如果可用,Underscore会使用本地的indexOf方法,否则会使用后备方案。因此,对于对象列表,您需要以其他方式实现它。

一个例子可能是

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

或者

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

1
如果您有复杂的对象,并且想在集合中查找一个对象以查找特定属性,只需使用以下代码:
 _.indexOf(arrayObj, _.findWhere(arrayObj, {id: 1})  );

其中,"arrayObj" 是对象集合,"id"是属性,"1"是需要搜索的值。


1
我正在使用find index。
 _.findIndex(array, searchValue); 

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接