【问题标题】:How to "uniqueify" a javascript array of objects?如何“唯一化”一个javascript对象数组?
【发布时间】:2018-06-23 19:35:02
【问题描述】:

如何删除数组中所有键和值都匹配的对象?我见过这个问题的变体,但仅针对特定领域。

例如,给定以下输入,输出将如下所示:

> var a = [
  {a:1, b:'x'},
  {a:1, b:'y'},
  {a:1, b:'y'},
  {a:2, b:'x'},
  {a:2, b:'y'},
  {a:2, b:'y'},
  {a:2, b:'x'},
  {b:'y', a:2},
  {a:2, b:'y', c:'surprise!'}
]
> blackbox(a)
[
  {a:1, b:'x'},
  {a:1, b:'y'},
  {a:2, b:'x'},
  {a:2, b:'y'},
  {a:2, b:'y', c:'surprise!'}
]

理想情况下,blackbox 不会使用密钥进行硬编码。

【问题讨论】:

    标签: javascript arrays object unique


    【解决方案1】:

    顺便说一句,这里是我现在拥有的 hack。它将每个(排序的)对象转换为一个字符串,并检查它之前是否看到过该字符串。

    无论如何,必须有一个更优雅的解决方案!

    > function uniq(a) {
      var keys = new Set();
      return a.filter(function(row) {
        var key  = Object.entries(row).sort().toString();
        var uniq = !keys.has(key);
        keys.add(key);
        return uniq;
      });
    }
    > a =
    [ { a: 1, b: 'x' },
      { a: 1, b: 'y' },
      { a: 1, b: 'y' },
      { a: 2, b: 'x' },
      { a: 2, b: 'y' },
      { a: 2, b: 'y' },
      { a: 2, b: 'x' },
      { b: 'y', a: 2 },
      { a: 2, b: 'y', c: 'surprise!' },
      { c: 'surprise!', a: 2, b: 'y' } ]
    > uniq(a)
    [ { a: 1, b: 'x' },
      { a: 1, b: 'y' },
      { a: 2, b: 'x' },
      { a: 2, b: 'y' },
      { a: 2, b: 'y', c: 'surprise!' } ]
    > b =
    [ { a: { b: 1, c: 2 }, b: 1 },
      { b: 1, a: { c: 2, b: 1 } },
      { a: { b: 1, c: 2 }, b: 2 } ]
    > uniq(b) // works because nested objects happen to be identical
    [ { a: { b: 1, c: 2 }, b: 1 }, { a: { b: 1, c: 2 }, b: 2 } ] 
    > c = 
    [ { a: { b: 1, c: 2 }, b: 1 },
      { b: 1, a: { c: 2, b: 1 } },
      { a: { b: 1, c: 2 }, b: 2 },
      { a: { b: 2, c: 1 }, b: 2 } ]
    > uniq(c) // fail on nested object
    [ { a: { b: 1, c: 2 }, b: 1 }, { a: { b: 1, c: 2 }, b: 2 } ]
    

    【讨论】:

    • 这应该是对您的问题的修改,而不是答案
    • 这是一个答案,因为它回答了我认为有用的特定用例。我希望有更好的答案,更通用,更优雅。