7 Map and Set
7 Map and Set
FR
23 octobre 2022
Map
Une Map (dictionnaire de donnée) permet, comme pour un Object , de stocker plusieurs éléments sous la
forme de clés valeurs. Sauf que cette fois, les clés peuvent être de n’importe qu’elle type.
Par exemple :
1 let map = new Map();
2
3 map.set('1', 'str1'); // une clé de type chaîne de caractère
4 map.set(1, 'num1'); // une clé de type numérique
5 map.set(true, 'bool1'); // une clé de type booléenne
6
7 // souvenez-vous, dans un `Object`, les clés sont converties en chaîne de carac
8 // alors que `Map` conserve le type d'origine de la clé,
9 // c'est pourquoi les deux appels suivants retournent des valeurs différentes:
10
11 alert( map.get(1) ); // 'num1'
12 alert( map.get('1') ); // 'str1'
13
14 alert( map.size ); // 3
Au travers de cet exemple nous pouvons voir, qu’à la différence des Objects , les clés ne sont pas converties en
chaîne de caractère. Il est donc possible d’utiliser n’importe quel type.
Nous devons donc utiliser les méthodes map : set , get et ainsi de suite.
Par exemple:
1 let john = { name: "John" };
2
3 // pour chaque utilisateur, nous stockons le nombre de visites
4 let visitsCountMap = new Map();
5
6 // john est utilisé comme clé dans la map
7 visitsCountMap.set(john, 123);
8
9 alert( visitsCountMap.get(john) ); // 123
Utiliser des objets comme clés est l’une des fonctionnalités les plus notables et les plus importantes de Map . La
même chose ne compte pas pour Object . Une chaîne de caractères comme clé dans Object est très bien,
mais nous ne pouvons pas utiliser un autre Object comme clé dans Object .
1 let john = { name: "John" };
2 let ben = { name: "Ben" };
3
4 let visitsCountObj = {}; // on créé notre object
5
6 visitsCountObj[ben] = 234; // essayez d'utiliser l'objet ben comme clé
7 visitsCountObj[john] = 123; // essayez d'utiliser l'objet john comme clé, l'obj
8
9 // C'est ce qui a été écrit!
10 alert( visitsCountObj["[object Object]"] ); // 123
Comme visitesCountObj est un objet, il convertit toutes les clés Object , telles que john et ben ci-dessus,
en la même chaîne de caractères "[object Object]" . Certainement pas ce que nous voulons.
Comment Map compare les clés
Pour tester l’égalité entre les clés, Map se base sur l’algorithme SameValueZero. C’est grosso modo la
même chose que l’opérateur de stricte égalité === , à la différence que NaN est considéré comme étant
égal à NaN . NaN peut donc être utilisé comme clé.
Chaining
Chaque appel à map.set retourne la map elle-même, ce qui nous permet d’enchaîner les appels:
1 map.set('1', 'str1')
2 .set(1, 'num1')
3 .set(true, 'bool1');
Par exemple :
1 let recipeMap = new Map([
2 ['cucumber', 500],
3 ['tomatoes', 350],
4 ['onion', 50]
5 ]);
6
7 // on parcourt les clés (les légumes)
8 for (let vegetable of recipeMap.keys()) {
9 alert(vegetable); // cucumber, tomatoes, onion
10 }
11
12 // on parcourt les valeurs (les montants)
13 for (let amount of recipeMap.values()) {
14 alert(amount); // 500, 350, 50
15 }
16
17 // on parcourt les entries (couple [clé, valeur])
18 for (let entry of recipeMap) { // équivalent à : recipeMap.entries()
19
20
alert(entry); // cucumber,500 (etc...)
}
Il est aussi possible d’utiliser forEach avec Map comme on pourrait le faire avec un tableau :
1 // array of [key, value] pairs
2 let map = new Map([
3 ['1', 'str1'],
4 [1, 'num1'],
5 [true, 'bool1']
6 ]);
7
8 alert( map.get('1') ); // str1
If we have a plain object, and we’d like to create a Map from it, then we can use built-in method
Object.entries(obj) that returns an array of key/value pairs for an object exactly in that format.
1 let obj = {
2 name: "John",
3 age: 30
4 };
5
6 let map = new Map(Object.entries(obj));
7
8 alert( map.get('name') ); // John
Here, Object.entries returns the array of key/value pairs: [ ["name","John"], ["age", 30] ] . That’s
what Map needs.
Object.fromEntries: Object from Map
We’ve just seen how to create Map from a plain object with Object.entries(obj) .
There’s Object.fromEntries method that does the reverse: given an array of [key, value] pairs, it creates
an object from them:
1 let prices = Object.fromEntries([
2 ['banana', 1],
3 ['orange', 2],
4 ['meat', 4]
5 ]);
6
7 // now prices = { banana: 1, orange: 2, meat: 4 }
8
9 alert(prices.orange); // 2
E.g. we store the data in a Map , but we need to pass it to a 3rd-party code that expects a plain object.
Here we go:
1 let map = new Map();
2 map.set('banana', 1);
3 map.set('orange', 2);
4 map.set('meat', 4);
5
6 let obj = Object.fromEntries(map.entries()); // make a plain object (*)
7
8 // done!
9 // obj = { banana: 1, orange: 2, meat: 4 }
10
11 alert(obj.orange); // 2
A call to map.entries() returns an iterable of key/value pairs, exactly in the right format for
Object.fromEntries .
That’s the same, because Object.fromEntries expects an iterable object as the argument. Not necessarily an
array. And the standard iteration for map returns same key/value pairs as map.entries() . So we get a plain
object with same key/values as the map .
Set
Set est une liste sans doublons.
● new Set(iterable) – crée le set et si un objet iterable est fourni (généralement un tableau), copie les
valeurs de celui-ci dans le set.
● set.add(value) – ajoute une valeur, renvoie le set lui-même.
● set.delete(value) – supprime la valeur, renvoie true si value existait au moment de l’appel, sinon
false .
● set.has(value) – renvoie true si la valeur existe dans l’ensemble, sinon false .
● set.clear() – supprime tout du set.
● set.size – est le nombre d’éléments.
Ce qu’il faut surtout savoir c’est que lorsque l’on appelle plusieurs fois set.add(value) avec la même valeur,
la méthode ne fait rien. C’est pourquoi chaque valeur est unique dans un Set .
Par exemple, nous souhaitons nous souvenir de tous nos visiteurs. Mais chaque visiteurs doit être unique.
1 let set = new Set();
2
3 let john = { name: "John" };
4 let pete = { name: "Pete" };
5 let mary = { name: "Mary" };
6
7 // visites, certains utilisateurs viennent plusieurs fois
8 set.add(john);
9 set.add(pete);
10 set.add(mary);
11 set.add(john);
12 set.add(mary);
13
14 // set conserve une fois chaque visiteurs
15 alert( set.size ); // 3
16
17 for (let user of set) {
18 alert(user.name); // John (puis Pete et Mary)
19 }
Nous aurions aussi pu utiliser un tableau ( Array ) en vérifiant avant chaque insertion que l’élément n’existe pas
en utilisant arr.find. Cependant les performances auraient été moins bonnes car cette méthode parcours chaque
élément du tableau. Set est beaucoup plus efficace car il est optimisé en interne pour vérifier l’unicité des
valeurs.
Parcourir un Set
Nous pouvons parcourir les éléments d’un Set avec for..of ou en utilisant forEach
1 let set = new Set(["oranges", "apples", "bananas"]);
2
3 for (let value of set) alert(value);
4
5 // même chose en utilisant forEach:
6 set.forEach((value, valueAgain, set) => {
7 alert(value);
8 });
A noter que la fonction de callback utilisée par forEach prend 3 arguments en paramètres: une value , puis la
même valeur valueAgain , et enfin le set lui-même.
C’est pour la compatibilité avec Map où le callback forEach passé possède trois arguments. Ça a l’air un peu
étrange, c’est sûr. Mais cela peut aider à remplacer facilement Map par Set dans certains cas, et vice versa.
Les méthodes pour parcourir les éléments d’une Map peuvent être utilisées :
Summary
Map – est une collection de clé valeurs.
Méthodes et propriétés:
● new Map([iterable]) – crée la map, avec un iterable facultatif (par exemple un tableau) de paires
[key,value] pour l’initialisation.
● map.set(key, value) – stocke la valeur par la clé, renvoie la map elle-même.
● map.get(key) – renvoie la valeur par la clé, undefined si key n’existe pas dans la map.
● map.has(key) – renvoie true si la key existe, false sinon.
● map.delete(key) – supprime la valeur par la clé, retourne true si key existait au moment de l’appel,
sinon false .
● map.clear() – supprime tout de la map.
● map.size – renvoie le nombre actuel d’éléments.
● new Set([iterable]) – crée le set avec un iterable facultatif (par exemple un tableau) de valeurs pour
l’initialisation.
● set.add(value) – ajoute une valeur (ne fait rien si value existe), renvoie le set lui-même.
● set.delete(value) – supprime la valeur, renvoie true si value existait au moment de l’appel, sinon
false .
● set.has(value) – renvoie true si la valeur existe dans le set sinon false .
● set.clear() – supprime tout du set.
● set.size – est le nombre d’éléments.
On ne peut pas dire que les éléments dans une Map ou un Set sont désordonnés car ils sont toujours
parcourut par ordre d’insertion. Il est cependant impossible de réorganiser les éléments ou bien de les retrouver
par leur index.
Exercices
importance: 5
Créez une fonction unique(arr) qui devrait renvoyer un tableau avec les éléments uniques d’arr.
Par exemple :
1 function unique(arr) {
2 /* your code */
3 }
4
5 let values = ["Hare", "Krishna", "Hare", "Krishna",
6 "Krishna", "Krishna", "Hare", "Hare", ":-O"
7 ];
8
9 alert( unique(values) ); // Hare, Krishna, :-O
P.S. Ici, les chaînes de caractères sont utilisées, mais elles peuvent être des valeurs de n’importe quel type.
solution
Anagrams sont des mots qui ont le même nombre de mêmes lettres, mais dans un ordre différent.
Par exemple :
1 nap - pan
2 ear - are - era
3 cheaters - hectares - teachers
Ecrivez une fonction aclean(arr) qui retourne un tableau nettoyé des anagrammes.
Par exemple :
De chaque groupe d’anagrammes ne devrait rester qu’un mot, peu importe lequel.
solution
Clés Iterables
importance: 5
Nous voulons obtenir un tableau de map.keys() dans une variable puis lui appliquer des méthodes spécifiques
aux tableaux, par ex: .push .
1 let map = new Map();
2
3 map.set("name", "John");
4
5 let keys = map.keys();
6
7 // Error: keys.push is not a function
8 keys.push("more");
solution
Cours précédent Prochain cours
Partager Carte du tutoriel
Commentaires
● Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request
au lieu de commenter.
● Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
● Pour insérer quelques bouts de code, utilisez la balise <code> , pour plusieurs lignes – enveloppez-les
avec la balise <pre> , pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)
0 Commentaires
1 S'identifier
Commencer la discussi…
S'IDENTIFIER AVEC
Nom
Partager