Why Set removes duplicate elements?The term Set, English for "set", comes from the mathematical concept of https://pt.wikipedia.org/wiki/Conjunto . From the definition, a set consists of elements (or no element, the empty set). https://math.stackexchange.com/a/223506/629569 It is only possible to state that a set contains or does not contain any element. It is not appropriate, therefore, to say that an element is present more than once (as opposed to what is possible in a list, for example).So it doesn't make sense that languages that implement this concept (like Set, JavaScript) allow the inclusion of the same element several times in one Set. In view of this, data structures representing the idea of a mathematical set are expected to have a mechanism to prevent the insertion of the same element more than once.Like Set removes duplicate elements?Elements can be added to a Set by method Set.prototype.add. To prevent equal values from being added to the set, https://262.ecma-international.org/11.0/#sec-set.prototype.add of the method makes a check before actually inserting the element.Thus, if the programmer calls the method add passing a value that already exists in the set, the insertion will not occur again – the Set will remain unchanged. Example:const set = new Set(); // Set(0) {}
set.add('foo'); // Set(1) {"foo"}
set.add('bar'); // Set(2) {"foo", "bar"}
// Elemento "foo" já existe, set será mantido inalterado.
set.add('foo'); // Set(2) {"foo", "bar"}
It is also worth mentioning that, in the instance of a new Set, the constructor can receive an iterable with the initial elements to be added. In this way, the implementation will go through each value of the iterable (which can be passed to the https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set#parameters ) and call Set.prototype.add for each element. Thus, if the supplied iterable has duplicate elements, the Set in question will not suffer the insertion of duplicate values.The comparison mechanism used by Set to determine whether two elements are equal is the https://262.ecma-international.org/11.0/#sec-samevaluezero .In short, JavaScript does not allow an instance of Set have duplicate elements.And the trigger to remove duplicate values from the array? How does it work?As we saw above, the builder Set accepts an iterable in your first argument, using the method add when iterating on each iterated value, which prevents repeated inserts.As JavaScript arrays are iterable by providing an array to the first constructor argument Set, each array value will be traveled, so that each single element of the array will be added to the built-in instance. For example:const set1 = new Set([1, 2, 3, 1]);
// É o mesmo que fazer:
const set2 = new Set();
set2.add(1);
set2.add(2);
set2.add(3);
set2.add(1); // Como já existe, o add não alterará o conjunto
Thus, a new set is created with each unrepeated element of the array. This same procedure can be done for any iterable, such as strings.Once the Set has been created, the duplicate elements of the array have already been removed. From there, it is necessary to create a new array, since most people, when providing an array, expect an array back. Of course. Set is a detail of the implementation ofgothm to remove duplicate elements from an array.That's what spread operator Do it. When used within a literal array, the spread itera on each element of an iterable (as is the case of Set, previously created) and adds, element to element, to the array in which it was applied.Once the new array has been created, there is no more to do. It's over. You already have a new array without repeated elements.When and why sometimes does this not work with objects?As we have seen above, the algorithm used by the method Set.prototype.add to determine whether two members are equal (or different) is the https://262.ecma-international.org/11.0/#sec-samevaluezero . The comparison SameValueZero, which, for objects, works similarly to the operator ===compare them via reference.To SameValueZero, two objects will be equal only if they have the same reference.Thus, although they have all equal members, all these objects are different for the SameValueZero (both Set created does not remove them by duplicity). See:const arr = [
{ id: 1 },
{ id: 1 },
{ id: 1 }
]; // Podem parecer objetos iguais, mas possuem referências diferentes,
// já que não se tratam do mesmo objeto.
// Logo, o Set não os remove por "duplicidade":
const set = new Set(arr);
// O "novo array" irá conter todos os mesmos três objetos:
const newArr = [...set];
console.log('Initial:', arr); //=> [{ id: 1 }, { id: 1 }, { id: 1 }]
console.log('Final:', newArr); //=> [{ id: 1 }, { id: 1 }, { id: 1 }]However, in this other example below, it is a list of three elements, the three being the same object. In that case, the Set removes it by duplicity. See:const obj = { id: 1 };
const arr = [
obj,
obj,
obj
]; // Todos os três elementos são objetos iguais (possuem a mesma referência).
// Logo, o Set os remove por duplicidade:
const set = new Set(arr);
// O "novo array" irá conter apenas um elemento.
const newArr = [...set];
console.log('Initial:', arr); //=> [{ id: 1 }, { id: 1 }, { id: 1 }]
console.log('Final:', newArr); //=> [{ id: 1 }]In cases where objects must be removed by some criterion of duplicity, therefore, the Set may not be ideal. In most cases, it is ideal to create a comparison algorithm in hand. https://pt.stackoverflow.com/a/474344/69296