Objet `Set`

Cet article explique l'objet Set.

Nous expliquerons l'objet Set à l'aide d'exemples pratiques.

YouTube Video

Objet Set

Set est un objet natif utilisé pour gérer des ensembles de valeurs uniques, sans doublons. Il permet d'éliminer les doublons et de vérifier l'existence d'une valeur plus simplement qu'avec les tableaux, et facilite la mise en œuvre des opérations ensemblistes, telles que l'union et l'intersection.

Notions de base : création et utilisation des Sets

Tout d'abord, voyons comment créer un Set, ajouter et supprimer des éléments, vérifier leur existence et obtenir sa taille.

Voici un exemple de base qui crée un nouveau Set et montre les méthodes add, has, delete et 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]
  • Comme le montre ce code, Set supprime automatiquement les valeurs primitives en double, et vous pouvez obtenir le nombre d’éléments grâce à size.

Méthodes d'itération

Set est itérable, vous pouvez donc le parcourir en utilisant for...of ou forEach. L'ordre correspond à l'ordre d'insertion.

Voici des exemples d'utilisation de for...of et 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});
  • La signature de rappel pour forEach est value, value, set (pour la compatibilité avec Map), mais en pratique, on n'utilise généralement que le premier argument value.

Conversion entre tableaux et Sets (utile pour supprimer les doublons)

Nous présentons ici une technique simple pour supprimer les doublons d'un tableau et comment convertir un Set en tableau.

Voici un exemple de suppression des doublons d'un tableau en le passant dans un 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]
  • Ce schéma est rapide et concis, il est donc couramment utilisé pour enlever les doublons d'un tableau. C'est particulièrement efficace pour les valeurs primitives.

Objets et gestion des références

Les objets dans un Set sont comparés par référence ; ainsi, différentes instances avec le même contenu sont considérées comme des éléments distincts.

Le code suivant montre ce qui se passe lorsque vous ajoutez des objets dans un 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)
  • La détection des doublons pour les objets se fait par identité de référence ; donc, si vous souhaitez dédupliquer selon le contenu uniquement, il faudra sérialiser ou traiter ces objets différemment.

Valeurs spéciales : gestion de NaN et de -0/+0

Set utilise la règle de comparaison Same-value-zero pour déterminer l'égalité des valeurs. Cette méthode de comparaison a les caractéristiques suivantes concernant les nombres :.

  • NaN est considéré comme égal à NaN.
  • +0 et -0 ne sont pas distingués et sont traités comme la même valeur.

Ainsi, lorsque vous ajoutez ces valeurs à un Set, le comportement suivant se produit :.

 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)
  • Dans une comparaison normale (NaN === NaN), cela retourne false, mais dans un Set, toutes les valeurs NaN sont considérées comme « la même valeur ».
  • +0 et -0 peuvent être distingués mathématiquement, mais dans un Set, ils sont simplement traités comme 0.
  • En conséquence, une seule valeur NaN et une seule valeur 0 restent dans le Set.
  • La règle de comparaison de Set est similaire à celle de Object.is, mais pas exactement identique. Object.is(+0, -0) renvoie false, mais dans un Set, ils sont considérés comme identiques. Merci de prendre note de cette différence.

Utilitaire courant : opérations sur les ensembles (union, intersection, différence)

Les opérations ensemblistes peuvent être exprimées plus clairement en utilisant Set. Voici des exemples courants d'implémentation.

Voici des exemples de fonctions pour union, intersection et difference.

 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]
  • Les opérations ensemblistes peuvent être écrites facilement en utilisant des filtres avec la combinaison de Set et de tableaux. Lors du traitement de grands ensembles de données, la performance O(1) de has rend les opérations plus rapides.

Exemple pratique : trouver la différence entre deux tableaux (détection des éléments ajoutés/supprimés)

L'exemple suivant montre comment utiliser un Set pour trouver la différence entre deux tableaux (une ancienne liste et une nouvelle liste). Cela permet d'identifier quels éléments ont été ajoutés et lesquels ont été supprimés.

 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] }
  • Cette méthode est très pratique pour détecter les différences dans des listes d'identifiants, des listes de tags, etc. Il est plus simple de l'utiliser avec des valeurs primitives.

Différences entre WeakSet et Set (gestion de la mémoire)

WeakSet est similaire à Set, mais il utilise des références faibles, ce qui permet à ses éléments d’être collectés par le ramasse-miettes. Voici quelques exemples d'utilisation basique 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 ne peut contenir que des objets et ne peut pas être itéré. Voici des exemples des contraintes de WeakSet : il ne contient que des objets et ne peut pas être itéré.

 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 est utile pour suivre temporairement la présence d'objets, mais vous ne pouvez pas énumérer ses éléments ni obtenir sa taille.

Performance et choix d'utilisation

Lorsque vous décidez d'utiliser ou non un Set, il est important de comprendre ses caractéristiques de performance et la nature de vos données.

  • has, add et delete fonctionnent généralement avec une performance quasi O(1) en moyenne. Ainsi, dans les situations où l'on vérifie souvent l'existence ou où l'on enlève des doublons, Set est souvent plus avantageux que les tableaux.
  • Faites attention si vous souhaitez dédupliquer des objets selon leurs contenus (valeurs). Puisque Set compare par référence, une méthode pratique consiste à utiliser des IDs ou autres clés, ou à sérialiser les objets en valeurs primitives avant de les utiliser dans un Set lorsque la comparaison sur les valeurs est nécessaire.
  • Set est particulièrement utile pour améliorer la lisibilité du code pour les collections de petite ou moyenne taille. En revanche, si vous gérez un très grand nombre d'éléments ou si vous convertissez fréquemment entre tableaux et Sets, il est recommandé de réaliser des benchmarks et des tests concrets.

Pièges courants

Set est pratique, mais si vous n'êtes pas conscient de ses spécifications, vous pourriez être surpris par des comportements inattendus. Voici quelques points typiques auxquels il faut faire attention :.

  • Les objets sont comparés par référence, donc même si leur contenu est identique, des objets différents ne seront pas considérés comme des doublons.
  • Set maintient l'ordre d'insertion, mais vous ne pouvez pas accéder aux éléments par index comme dans un tableau. Si vous souhaitez accéder par index, convertissez d'abord le Set en tableau.
  • WeakSet ne peut pas être énuméré et ne peut contenir que des objets. Notez que son champ d'application est limité.
  • NaN est traité comme la même valeur, et +0 et -0 ne sont pas distingués. Cela est dû à la règle de comparaison Same-value-zero.

Résumé

Set est une structure de données pratique qui permet de manipuler intuitivement des collections de valeurs uniques. Vous pouvez l'utiliser pour supprimer les doublons d'un tableau, effectuer des vérifications rapides d'existence ou implémenter des opérations ensemblistes comme l'union et l'intersection avec un code simple et lisible.

En revanche, puisque les objets sont comparés par référence, des mesures supplémentaires sont nécessaires si vous souhaitez comparer selon leur contenu.

En comprenant ces caractéristiques et en les utilisant à bon escient, Set devient un choix puissant pour améliorer la lisibilité et la maintenabilité du code.

Vous pouvez suivre l'article ci-dessus avec Visual Studio Code sur notre chaîne YouTube. Veuillez également consulter la chaîne YouTube.

YouTube Video