DEV Community

loading...

Discussion on: Remove Duplicates With Set() - Full-Stop

Collapse
monfernape profile image
Usman Khalil

Does that work with array of objects, having similar properties?

Collapse
merri profile image
Vesa Piittinen

No.

new Set([{ a: 1 }, { a: 1 }]).size
// -> 2
Enter fullscreen mode Exit fullscreen mode
Collapse
bytebodger profile image
Adam Nathaniel Davis Author • Edited

As Vesa demonstrated, this only works on scalar values. The reason is pretty simple:

console.log({a: 1} === {a: 1}); // false
Enter fullscreen mode Exit fullscreen mode

You could kinda sorta get around this using the old JSON.stringify() hack:

const set1 = new Set([{ a: 1 }, { a: 1 }]);
console.log(set1.size); // 2

const set2 = new Set([JSON.stringify({ a: 1 }), JSON.stringify({ a: 1 })]);
console.log(set2.size); // 1

const set3 = new Set([['a'], ['a']]);
console.log(set3.size); // 2

const set4 = new Set([JSON.stringify(['a']), JSON.stringify(['a'])]);
console.log(set4.size); // 1
Enter fullscreen mode Exit fullscreen mode

Although that only "works" if the keys/elements are in the same order. It would also fail in any scenario where JSON.stringify() would fail - e.g., if the objects/arrays contain functions.

Collapse
kretaceous profile image
Abhijit Hota

Came here to comment that. @bytebodger you might want to add that as a catch.

Because this particular gotcha has been a pain for me earlier.

Collapse
bytebodger profile image
Adam Nathaniel Davis Author • Edited

I did edit the original article slightly to indicate that it works with scalar (primitive) values. But I hadn't really thought of this as much of a "gotcha", because two objects that look the same... are not the same.

FWIW, this approach actually works with arrays and objects, if they are truly the same array/object. In other words, you can do something like this:

const anObject = {one: 'uno', two: 'dos'};
const anotherObject = anObject;
const anArray = [anObject, anotherObject];
const noDupes = [...new Set(anArray)];
Enter fullscreen mode Exit fullscreen mode

And the resulting noDupes array will only contain one object. But if you do this:

const anObject = {one: 'uno', two: 'dos'};
const anotherObject = {one: 'uno', two: 'dos'};
const anArray = [anObject, anotherObject];
const noDupes = [...new Set(anArray)];
Enter fullscreen mode Exit fullscreen mode

noDupes will contain two objects. Because, even though anObject and anotherObject look the same to our eye, they are not the same value.