Le moyen le plus simple de fusionner ES6 Maps / Sets?

Existe-t-il un moyen simple de fusionner ES6 Maps ensemble (comme Object.assign )? Et pendant que nous sommes là, qu'en est-il des ES6 Sets (comme Array.concat )?

Pour les ensembles:

 var merged = new Set([...set1, ...set2, ...set3]) 

Pour les cartes:

 var merged = new Map([...map1, ...map2, ...map3]) 

Notez que si plusieurs cartes ont la même clé, la valeur de la carte fusionnée sera la valeur de la dernière carte de fusion avec cette clé.

Voici ma solution en utilisant les générateurs:

Pour les cartes:

 let map1 = new Map(), map2 = new Map(); map1.set('a', 'foo'); map1.set('b', 'bar'); map2.set('b', 'baz'); map2.set('c', 'bazz'); let map3 = new Map(function*() { yield* map1; yield* map2; }()); console.log(Array.from(map3)); // Result: [ [ 'a', 'foo' ], [ 'b', 'baz' ], [ 'c', 'bazz' ] ] 

Pour les ensembles:

 let set1 = new Set(['foo', 'bar']), set2 = new Set(['bar', 'baz']); let set3 = new Set(function*() { yield* set1; yield* set2; }()); console.log(Array.from(set3)); // Result: [ 'foo', 'bar', 'baz' ] 

Pour des raisons que je ne comprends pas, vous ne pouvez pas directement ajouter le contenu d'un Set à un autre avec une opération intégrée.

Il semblerait naturel que .add() ait détecté que vous passiez un autre objet Set, puis prenez tous les éléments hors de cet ensemble (c'est à dire mon objet Set, avant qu'il y ait une spécification ES6 Set). Mais, ils ont choisi de ne pas l'appliquer de cette façon.

Au lieu de cela, vous pouvez le faire avec une seule ligne .forEach() :

 var s = new Set([1,2,3]); var t = new Set([4,5,6]); t.forEach(s.add, s); console.log(s); // 1,2,3,4,5,6 

Et, pour une Map , vous pouvez le faire:

 var s = new Map([["key1", 1], ["key2", 2]]); var t = new Map([["key3", 3], ["key4", 4]]); t.forEach(function(value, key) { s.set(key, value); }); 

Pour fusionner les ensembles dans les ensembles de tableaux, vous pouvez le faire

 var Sets = [set1, set2, set3]; var merged = new Set([].concat(...Sets.map(set => Array.from(set)))); 

Il est légèrement mystérieux pour moi pourquoi le suivant, qui devrait être équivalent, échoue au moins à Babel:

 var merged = new Set([].concat(...Sets.map(Array.from))); 

Non, il n'y a pas d'opérations intégrées pour ces derniers, mais vous pouvez facilement les créer eux-mêmes:

 Map.prototype.assign = function(...maps) { for (const m of maps) for (const kv of m) this.add(...kv); return this; }; Set.prototype.concat = function(...sets) { const c = this.constructor; let res = new (c[Symbol.species] || c)(); for (const set of [this, ...sets]) for (const v of set) res.add(v); return res; }; 

La réponse approuvée est excellente, mais cela crée un nouvel ensemble à chaque fois.

Si vous souhaitez transformer un objet existant à la place, utilisez une fonction helper.

Ensemble

 function concatSets(set, ...iterables) { for (const iterable of iterables) { for (const item of iterable) { set.add(item); } } } 

Usage:

 const setA = new Set([1, 2, 3]); const setB = new Set([4, 5, 6]); const setC = new Set([7, 8, 9]); concatSets(setA, setB, setC); // setA will have items 1, 2, 3, 4, 5, 6, 7, 8, 9 

Carte

 function concatMaps(map, ...iterables) { for (const iterable of iterables) { for (const item of iterable) { map.set(...item); } } } 

Usage:

 const mapA = new Map().set('S', 1).set('P', 2); const mapB = new Map().set('Q', 3).set('R', 4); concatMaps(mapA, mapB); // mapA will have items ['S', 1], ['P', 2], ['Q', 3], ['R', 4]