删除对象数组中的重复项Javascript

时间:2016-03-16 09:55:40

标签: javascript arrays underscore.js

我有一个对象数组

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}]

我正在寻找一种有效的方式(如果可能的话O(log(n)))来删除重复项并最终使用

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}]

我已尝试_.uniq甚至_.contains,但找不到令人满意的解决方案。

谢谢!

编辑:该问题已被确定为另一个问题的副本。我在帖子之前看到了这个问题,但它没有回答我的问题,因为它是一个对象数组(而不是一个2-dim数组,感谢Aaron),或者至少其他问题的解决方案在我的情况下不起作用。

8 个答案:

答案 0 :(得分:19)

普通javascript(ES2015),使用Set



var list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }];

var uniq = new Set(list.map(e => JSON.stringify(e)));

var res = Array.from(uniq).map(e => JSON.parse(e));

document.write(JSON.stringify(res));




答案 1 :(得分:15)

尝试使用以下内容:

list = list.filter((elem, index, self) => self.findIndex(
    (t) => {return (t.x === elem.x && t.y === elem.y)}) === index)

答案 2 :(得分:12)

Vanilla JS版:

function dedupe(arr) {
  return arr.reduce(function (p, c) {

    // create an identifying id from the object values
    var id = [c.x, c.y].join('|');

    // if the id is not found in the temp array
    // add the object to the output array
    // and add the key to the temp array
    if (p.temp.indexOf(id) === -1) {
      p.out.push(c);
      p.temp.push(id);
    }
    return p;

  // return the deduped array
  }, { temp: [], out: [] }).out;
}

dedupe(list);

DEMO

答案 3 :(得分:5)

我会将Arrayr.prototype.reduceArrayr.prototype.some方法与spread运算符结合使用。

<强> 1。明确的解决方案。基于对数组对象的完整知识包含。

list = list.reduce((r, i) => 
  !r.some(j => i.x === j.x && i.y === j.y) ? [...r, i] : r
, [])

这里我们对比较对象结构有严格的限制:{x: N, y: M}[{x:1, y:2}, {x:1, y:2, z:3}]将被过滤为[{x:1, y:2}]

<强> 2。通用解决方案JSON.stringify() 。比较对象可以包含任意数量的任何属性。

list = list.reduce((r, i) => 
  !r.some(j => JSON.stringify(i) === JSON.stringify(j)) ? [...r, i] : r
, [])

此方法对属性顺序有限制,因此[{x:1, y:2}, {y:2, x:1}]不会被过滤。

第3。通用解决方案Object.keys() 。订单无关紧要。

list = list.reduce((r, i) => 
  !r.some(j => !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])

这种方法有另一个限制:比较对象必须具有相同的键列表。 因此,[{x:1, y:2}, {x:1}]会被过滤,尽管存在明显差异。

<强> 4。通用解决方案,Object.keys() + .length

list = list.reduce((r, i) => 
  !r.some(j => Object.keys(i).length === Object.keys(j).length 
    && !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])

使用最后一个方法,通过键的数量,键本身和键值来比较对象。

我创建了一个Plunker来玩它。

答案 4 :(得分:4)

在检查是否已经在O(n)中的temorary对象中之后过滤数组。

&#13;
&#13;
var list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }],
    filtered = function (array) {
        var o = {};
        return array.filter(function (a) {
            var k = a.x + '|' + a.y;
            if (!o[k]) {
                o[k] = true;
                return true;
            }
        });
    }(list);

document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
&#13;
&#13;
&#13;

答案 5 :(得分:1)

以下内容可行:

var a = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];

var b = _.uniq(a, function(v) { 
    return v.x && v.y;
})

console.log(b);  // [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 } ]

答案 6 :(得分:0)

一个适用于ES6 +的衬垫

如果要通过x和y查找uniq:

arr.filter((v,i,a)=>a.findIndex(t=>(t.x === v.x && t.y===v.y))===i)

如果要通过所有属性查找唯一性:

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)

答案 7 :(得分:0)

使用lodash,您可以使用此单线:

 _.uniqBy(list, e => { return e.x && e.y })