使用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}] 
笔记:
- 用于比较的callback返回值
- 具有唯一返回值的第一个比较对象用作唯一
- underscorejs.org演示没有callback用法
- 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]]
用下划线我不得不在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')