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

kwn*_*kwn 22 javascript arrays underscore.js

我有一个对象数组

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}]
Run Code Online (Sandbox Code Playgroud)

而且我正在寻找一种有效的方法(如果可能的话O(log(n)))来删除重复项并最终结束

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}]
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

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

isv*_*all 25

简单的javascript(ES2015),使用 Set

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

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

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

document.write(JSON.stringify(res));
Run Code Online (Sandbox Code Playgroud)

  • 在ES2015中编写代码时,不应该使用var! (5认同)
  • `stringify`和`parse`看起来不是实现这一目标的最佳方式. (3认同)

Lav*_*N R 16

尝试使用以下内容:

list = list.filter((elem, index, self) => self.findIndex(
    (t) => {return (t.x === elem.x && t.y === elem.y)}) === index)
Run Code Online (Sandbox Code Playgroud)

  • 这是完美的。谢谢 (2认同)

And*_*ndy 14

香草JS版:

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

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

console.log(dedupe(list));
Run Code Online (Sandbox Code Playgroud)

DEMO


dhi*_*ilt 7

我将结合使用Arrayr.prototype.reduceArrayr.prototype.some方法与传播算子。

1.明确的解决方案。基于对数组对象包含的完全了解。

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

在这里,我们有比较的对象结构严格限制:{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
, [])
Run Code Online (Sandbox Code Playgroud)

这种方法对属性顺序有限制,因此[{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
, [])
Run Code Online (Sandbox Code Playgroud)

这种方法还有另一个局限性:被比较的对象必须具有相同的键列表。因此[{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
, [])
Run Code Online (Sandbox Code Playgroud)

在最后一种方法中,将通过键的数量,键本身和键值来比较对象。

我创建了一个Plunker来玩。


chi*_*ens 6

ES6+ 的 1 个衬垫

如果你想通过 x 和 y 找到 uniq:

arr.filter((v,i,a)=>a.findIndex(t=>(t.x === v.x && t.y===v.y))===i)
Run Code Online (Sandbox Code Playgroud)

如果您想查找所有属性的唯一性:

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
Run Code Online (Sandbox Code Playgroud)