使用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')