Objeto `Set`
Este artigo explica o objeto Set.
Vamos explicar o objeto Set com exemplos práticos.
YouTube Video
Objeto Set
Set é um objeto incorporado usado para lidar com coleções de valores únicos, sem duplicatas. Ele permite que você escreva eliminações de duplicados e verificações de existência de forma mais simples do que com arrays, e facilita a implementação de operações de conjuntos como união e interseção.
Noções básicas: Criando e usando Sets
Primeiro, vamos ver como criar um Set, adicionar e remover elementos, verificar existência e obter seu tamanho.
Abaixo está um padrão básico que cria um novo Set e demonstra add, has, delete e size.
1// Create a Set and demonstrate add, has, delete, and size
2const s = new Set();
3
4s.add(1);
5s.add(2);
6s.add(2); // duplicate, ignored
7
8console.log(s.has(1)); // true
9console.log(s.has(3)); // false
10
11s.delete(2);
12console.log(s.size); // 1
13
14console.log([...s]); // [1]
- Como mostrado neste código,
Setremove automaticamente valores primitivos duplicados, e você pode obter o número de elementos usandosize.
Métodos de iteração
Set é iterável, então você pode percorrê-lo usando for...of ou forEach. A ordem é a ordem de inserção.
Aqui estão formas típicas de usar for...of e forEach.
1// Iterate a Set with for...of and forEach
2const s = new Set(['a', 'b', 'c']);
3
4for (const v of s) {
5 console.log('for...of:', v);
6}
7
8s.forEach((value, sameValue, setRef) => {
9 // Note: second arg is same as first for Set API to match Map signature
10 console.log('forEach:', value);
11});- A assinatura da função callback para
forEachévalor, valor, conjunto(por compatibilidade com Map), mas na prática, normalmente só é necessário o primeiro argumentovalor.
Conversão entre Arrays e Sets (útil para remoção de duplicatas)
Aqui mostramos uma técnica simples para remover duplicatas de um array, e como converter um Set de volta para um array.
Abaixo está um exemplo de remoção de duplicatas de um array através do uso de um Set.
1// Deduplicate an array using Set
2const arr = [1, 2, 2, 3, 3, 3];
3const deduped = [...new Set(arr)];
4console.log(deduped); // [1, 2, 3]
5
6// Convert a Set to an array using Array.from
7const s = new Set([4, 5, 6]);
8const arrFromSet = Array.from(s);
9console.log(arrFromSet); // [4, 5, 6]
- Este padrão é curto e rápido, por isso é frequentemente usado para remover duplicatas de arrays. É especialmente eficaz para valores primitivos.
Objetos e tratamento de referências
Objetos em um Set são comparados por referência, então diferentes instâncias com o mesmo conteúdo são tratadas como elementos distintos.
O código a seguir demonstra o que acontece quando você adiciona objetos a um Set.
1// Objects are compared by reference in a Set
2const obj1 = { x: 1 };
3const obj2 = { x: 1 };
4
5const s = new Set();
6s.add(obj1);
7s.add(obj2);
8
9console.log(s.size); // 2 (different references)
10console.log(s.has(obj1)); // true
11console.log(s.has({ x: 1 })); // false (different object)
- A detecção de duplicatas para objetos é baseada na identidade de referência, então se você quiser remover duplicatas com base apenas no conteúdo do objeto, será necessário serializá-los ou processá-los de outra forma.
Valores especiais: Tratamento de NaN e -0/+0
Set utiliza a regra de comparação Same-value-zero para determinar a igualdade de valores. Este método de comparação tem as seguintes características em relação a números:.
NaNé considerado igual aNaN.+0positivo e-0negativo não são distinguidos e são tratados como o mesmo valor.
Portanto, ao adicionar esses valores a um Set, ocorre o seguinte comportamento:.
1// NaN and zero behavior in Set
2const s = new Set();
3
4s.add(NaN);
5s.add(NaN);
6console.log(s.size); // 1 (NaN considered the same)
7
8s.add(+0);
9s.add(-0);
10console.log(s.size); // still 2 (NaN + 0)
11console.log([...s]); // [NaN, 0] (order may vary but only one zero)
- Em uma comparação normal (
NaN === NaN), retornafalse, mas dentro de umSet, todos os valoresNaNsão considerados 'o mesmo valor'. - +0 e -0 podem ser diferenciados matematicamente, mas em um
Set, ambos são considerados simplesmente como0. - Como resultado, apenas um
NaNe um0permanecem noSet. - A regra de comparação do
Seté semelhante à doObject.is, mas não é exatamente a mesma.Object.is(+0, -0)retornafalse, mas em umSet, eles são considerados idênticos. Por favor, atente a essa diferença.
Utilidade comum: Operações de conjunto (União, Interseção, Diferença)
Operações de conjuntos podem ser escritas de forma mais clara usando Set. Abaixo estão exemplos comuns de implementação.
Aqui estão exemplos de funções para união, interseção e diferença.
1// Set operations: union, intersection, difference
2function union(a, b) {
3 return new Set([...a, ...b]);
4}
5
6function intersection(a, b) {
7 return new Set([...a].filter(x => b.has(x)));
8}
9
10function difference(a, b) {
11 return new Set([...a].filter(x => !b.has(x)));
12}
13
14// Demo
15const A = new Set([1, 2, 3]);
16const B = new Set([3, 4, 5]);
17
18console.log('union', [...union(A, B)]); // [1,2,3,4,5]
19console.log('intersection', [...intersection(A, B)]); // [3]
20console.log('difference A\\B', [...difference(A, B)]); // [1,2]
- Operações de conjuntos podem ser escritas simplesmente usando filtros com a combinação de
Sete arrays. Ao lidar com grandes volumes de dados, a performance O(1) dehastorna as operações mais rápidas.
Exemplo prático: Encontrando diferenças entre arrays (detectando itens adicionados/removidos)
O exemplo a seguir demonstra como usar um Set para encontrar a diferença entre dois arrays (uma lista antiga e uma lista nova). Isso permite identificar quais elementos foram adicionados e quais foram removidos.
1// Find added and removed items between two arrays
2function diffArrays(oldArr, newArr) {
3 const oldSet = new Set(oldArr);
4 const newSet = new Set(newArr);
5
6 const added = [...newSet].filter(x => !oldSet.has(x));
7 const removed = [...oldSet].filter(x => !newSet.has(x));
8
9 return { added, removed };
10}
11
12const oldList = [1, 2, 3];
13const newList = [2, 3, 4, 5];
14
15console.log(diffArrays(oldList, newList));
16// { added: [4,5], removed: [1] }
- Este método é muito conveniente para detectar diferenças em listas de IDs, listas de tags e situações semelhantes. É mais simples de usar com valores primitivos.
Diferenças entre WeakSet e Set (Gerenciamento de Memória)
WeakSet é semelhante ao Set, mas utiliza referências fracas, permitindo que seus itens sejam coletados pelo garbage collector. A seguir, demonstrações de usos básicos de WeakSet.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3let obj = { id: 1 };
4ws.add(obj);
5
6console.log(ws.has(obj)); // true
7
8obj = null; // Now the object is eligible for GC; WeakSet won't prevent collection
WeakSet só pode conter objetos e não pode ser iterado. Abaixo, exemplos das restrições do WeakSet—ele só armazena objetos e não pode ser iterado.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3
4// --- Only objects can be added ---
5try {
6 ws.add(1); // number
7} catch (e) {
8 console.log("Error: WeakSet can only store objects. Adding a number is not allowed.");
9}
10
11try {
12 ws.add("text"); // string
13} catch (e) {
14 console.log("Error: WeakSet can only store objects. Adding a string is not allowed.");
15}
16
17// --- WeakSet is not iterable ---
18try {
19 for (const value of ws) {
20 console.log(value);
21 }
22} catch (e) {
23 console.log("Error: WeakSet is not iterable. You cannot use for...of to loop over its elements.");
24}
25
26// --- Cannot convert to array ---
27try {
28 console.log([...ws]);
29} catch (e) {
30 console.log("Error: WeakSet cannot be converted to an array because it does not support iteration.");
31}
32
33// The object becomes eligible for garbage collection
34let obj = { id: 1 };
35ws.add(obj);
36obj = null;WeakSeté útil para rastrear temporariamente a presença de objetos, mas você não pode enumerar seus elementos ou obter seu tamanho.
Performance e quando escolher usar
Ao decidir se deve usar um Set, é importante entender suas características de performance e a natureza de seus dados.
has,addedeletenormalmente operam com performance quase O(1) em média. Portanto, em cenários onde você verifica frequentemente a existência ou remove duplicatas,Seté geralmente mais vantajoso do que arrays.- Seja cuidadoso se quiser remover duplicatas de objetos com base em seus conteúdos (valores). Como o
Setcompara por referência, uma forma prática é usar IDs ou outras chaves, ou serializar os objetos para valores primitivos antes de usar Sets quando for necessária a comparação baseada em valores. Seté particularmente útil para melhorar a legibilidade do código em coleções de pequeno a médio porte. Por outro lado, se você está lidando com um número muito grande de elementos ou convertendo frequentemente entre arrays e Sets, é recomendado fazer benchmarks e testes reais.
Armadilhas comuns
Set é conveniente, mas se você não estiver atento às suas especificações, pode se deparar com comportamentos inesperados. Aqui estão alguns pontos típicos para tomar cuidado:.
- Objetos são comparados por referência, então mesmo que o conteúdo seja o mesmo, objetos diferentes não são considerados duplicados.
Setmantém a ordem de inserção, mas você não pode acessar elementos por índice como em arrays. Se quiser acessar por índice, converta oSetpara um array primeiro.WeakSetnão pode ser enumerado, e só pode armazenar objetos. Observe que suas aplicações são limitadas.NaNé tratado como o mesmo valor, e+0e-0não são distinguidos. Isto se deve à regra de comparação Same-value-zero.
Resumo
Set é uma estrutura de dados conveniente que permite lidar com coleções de valores únicos de forma intuitiva. Você pode usá-lo para remover duplicatas de arrays, fazer verificações rápidas de existência ou implementar operações de conjuntos como união e interseção com código simples e legível.
Por outro lado, como objetos são comparados por referência, medidas extras são necessárias se você quiser julgar igualdade com base no conteúdo deles.
Compreendendo essas características e usando-as adequadamente, o Set se torna uma escolha poderosa para melhorar a legibilidade e a manutenção do código.
Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.