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

时间:2012-03-29 10:49:26

标签: javascript json underscore.js

我有这种阵列:

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

我想过滤它:

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

我尝试使用_.uniq,但我想因为{ "a" : "1" }不等于它本身,所以它不起作用。有没有办法为下划线uniq提供一个覆盖等于函数?

13 个答案:

答案 0 :(得分:231)

.uniq / .unique接受回调

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. 用于比较的回调返回值
  2. 具有唯一返回值的第一个比较对象,用作唯一
  3. underscorejs.org演示没有回调使用
  4. lodash.com显示用法
  5. 另一个例子: using the callback to extract car makes, colors from a list

答案 1 :(得分:38)

如果您希望根据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'}]

答案 2 :(得分:17)

实施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" } ]

答案 3 :(得分:15)

当我有属性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}]

答案 4 :(得分:11)

使用underscore unique lib对我有用,我在_id的基础上使列表唯一,然后返回_id的String值:

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

答案 5 :(得分:10)

这是一个简单的解决方案,它使用深层对象比较来检查重复项(不需要转换为JSON,这是低效和hacky)

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;
});

如果它们在数组中稍后有副本,它会过滤掉所有元素 - 这样就可以保留最后一个重复的元素。

重复使用_.isEqual的测试会在两个对象之间执行优化的深度比较,请参阅underscore isEqual documentation以获取更多信息。

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

答案 6 :(得分:8)

lodash 4.6.1 docs以对象密钥相等为例:

_.uniqWith(objects, _.isEqual);

https://lodash.com/docs#uniqWith

答案 7 :(得分:7)

尝试迭代器功能

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

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

_.uniq(x,false,function(i){  

   return i[0]   //'a','b'

})
  

=&GT; [[ '一个',1],[ 'B',2]]

答案 8 :(得分:3)

这是我的解决方案(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 ] ]

答案 9 :(得分:3)

下划线我必须在 iteratee 函数中使用 String()

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

答案 10 :(得分:0)

我想以一种简单的写作方式解决这个简单的解决方案,只需要一点点计算费用......但是它不是一个具有最小变量定义的简单解决方案,是吗?

function uniq(ArrayObjects){
  var out = []
  ArrayObjects.map(obj => {
    if(_.every(out, outobj => !_.isEqual(obj, outobj))) out.push(obj)
  })
  return out
}

答案 11 :(得分:0)

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) { 
        return JSON.stringify(f); 
    }), function (gr) { 
        return gr[0]; 
    }
);

让我们分解一下。首先,让我们按照数组的字符串值对数组项进行分组

var grouped = _.groupBy(foo, function (f) { 
    return JSON.stringify(f); 
});

grouped如下:

{
    '{ "a" : "1" }' = [ { "a" : "1" } { "a" : "1" } ],
    '{ "b" : "2" }' = [ { "b" : "2" } ]
}

然后让我们从每个组中抓取第一个元素

var bar = _.map(grouped, function(gr)
    return gr[0]; 
});

bar看起来像: [ { "a" : "1" }, { "b" : "2" } ]

将它们放在一起:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) { 
        return JSON.stringify(f); 
    }), function (gr) { 
        return gr[0]; 
    }
);

答案 12 :(得分:-5)

你可以用简写的方式做到:

_.uniq(foo, 'a')