0

How does one remove objects in an array that match across all keys and values? I've seen variations of this question but only for a particular field.

For example, given the following input the output would look like so:

> 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!'}
]

Ideally blackbox isn't hard-coded with the keys.

1 Answer 1

1

BTW, here the hack that I have now. It turns each (sorted) object into a string and checks to see if it's seen that string before.

Regardless, there's got to be a more elegant solution out there!

> 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 } ]
Sign up to request clarification or add additional context in comments.

2 Comments

This should be an edit to your question, not an answer
It's an answer because it answers a specific use case that I think will be useful. I'm hoping that there are better answers that are more general and more elegant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.