underscore: _.union doesn't work with arrays of objects

_.union will always produce duplicates when passed arrays of objects.

e.g. _.union( [ { a:1 } ], [ { a:1 } ]) will return [ { a:1 }, { a:1 } ]

Perversely, underscore’s own isEqual function will tell you that the objects in question are equal. Maybe we could have a flag/option which dictates the equality comparison to use, or the option to pass in a comparator?

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Comments: 32 (12 by maintainers)

Commits related to this issue

Most upvoted comments

This thread inspired me to add _.intersectionWith, _.differenceWith, _.unionWith, and _.uniqWith to handle comparison customization in my own code.

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

I’m surprised it doesn’t already accept the comparison function. 👍

_.intersectionWith, _.differenceWith, _.unionWith, and _.uniqWith

Wouldn’t it be a nicer API to just allow the comparison function to be optionally passed as the final argument, instead of minting four new functions?

@jdalton good point on the comparisons, but wouldn’t you usually use a key for unique on a collection rather than forcing Underscore to detect the entire difference between the objects?

Wouldn’t the following solve @wilhen01 's request (albeit more verbose than desired)

_.chain([{ a: 1 }]).union( [{a: 1}]).unique('a').value();
//=> [{a: 1}]