使用Underscore for Javascript删除重复的对象

我有这样的数组:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ]; 

我想过滤它有:

 var bar = [ { "a" : "1" }, { "b" : "2" }]; 

我尝试使用_.uniq,但我猜是因为{ "a" : "1" }不等于自己,它不起作用。 有没有办法提供一个重写等于函数的下划线uniq?

.uniq / .unique接受callback

 var list = [{a:1,b:5},{a:1,c:5},{a:2},{a:3},{a:4},{a:3},{a:2}]; var uniqueList = _.uniq(list, function(item, key, a) { return item.a; }); // uniqueList = [Object {a=1, b=5}, Object {a=2}, Object {a=3}, Object {a=4}] 

笔记:

  1. 用于比较的callback返回值
  2. 具有唯一返回值的第一个比较对象用作唯一
  3. underscorejs.org演示没有callback用法
  4. lodash.com显示用法

另外一个例子: 使用callback提取汽车制造,从一个列表的颜色

如果你想删除基于ID的重复,你可以做这样的事情:

 var res = [ {id: 1, content: 'heeey'}, {id: 2, content: 'woah'}, {id: 1, content:'foo'}, {id: 1, content: 'heeey'}, ]; var uniques = _.map(_.groupBy(res,function(doc){ return doc.id; }),function(grouped){ return grouped[0]; }); //uniques //[{id: 1, content: 'heeey'},{id: 2, content: 'woah'}] 

实施Shiplu的答案。

 var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ]; var x = _.uniq( _.collect( foo, function( x ){ return JSON.stringify( x ); })); console.log( x ); // returns [ { "a" : "1" }, { "b" : "2" } ] 

当我有一个属性ID,这是我在下划线的优先方式:

 var x = [{i:2}, {i:2, x:42}, {i:4}, {i:3}]; _.chain(x).indexBy("i").values().value(); // > [{i:2, x:42}, {i:4}, {i:3}] 

这是一个简单的解决scheme,它使用深度对象比较来检查重复项(而不是转换为JSON,这是效率低下和黑客)

 var newArr = _.filter(oldArr, function (element, index) { // tests if the element has a duplicate in the rest of the array for(index += 1; index < oldArr.length; index += 1) { if (_.isEqual(element, oldArr[index])) { return false; } } return true; }); 

它过滤掉所有元素,如果他们在数组中有一个重复的 – 这样最后一个重复的元素被保留。

对重复的testing使用_.isEqual ,在两个对象之间执行优化的深度比较,请参阅下划线isEqual文档以获取更多信息。

编辑:更新使用_.filter这是一个更清洁的方法

使用下划线独特的 lib下面正在为我工​​作,我做基于_id的列表唯一,然后返回_id的string值:

 var uniqueEntities = _.uniq(entities, function (item, key, a) { return item._id.toString(); }); 

尝试迭代器function

例如,你可以返回第一个元素

 x = [['a',1],['b',2],['a',1]] _.uniq(x,false,function(i){ return i[0] //'a','b' }) 

=> [['a',1],['b',2]]

lodash 4.6.1文档有这个作为对象关键字相等的例子:

_.uniqWith(objects, _.isEqual);

https://lodash.com/docs#uniqWith

下划线我不得不在iteratee函数中使用String()

 function isUniq(item) { return String(item.user); } var myUniqArray = _.uniq(myArray, isUniq); 

这是我的解决scheme(coffeescript):

 _.mixin deepUniq: (coll) -> result = [] remove_first_el_duplicates = (coll2) -> rest = _.rest(coll2) first = _.first(coll2) result.push first equalsFirst = (el) -> _.isEqual(el,first) newColl = _.reject rest, equalsFirst unless _.isEmpty newColl remove_first_el_duplicates newColl remove_first_el_duplicates(coll) result 

例:

 _.deepUniq([ {a:1,b:12}, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ],[ 2, 1, 2, 1 ], {a:1,b:12} ]) //=> [ { a: 1, b: 12 }, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ] ] 

你可以用一个简写来做:

_.uniq(foo, 'a')