Existe-t-il un moyen de map
/ reduce
/ filter
/ etc a Set
en JavaScript ou devrai-je écrire le mien?
Voici quelques Set.prototype
extensions sensibles
Set.prototype.map = function map(f) {
var newSet = new Set();
for (var v of this.values()) newSet.add(f(v));
return newSet;
};
Set.prototype.reduce = function(f,initial) {
var result = initial;
for (var v of this) result = f(result, v);
return result;
};
Set.prototype.filter = function filter(f) {
var newSet = new Set();
for (var v of this) if(f(v)) newSet.add(v);
return newSet;
};
Set.prototype.every = function every(f) {
for (var v of this) if (!f(v)) return false;
return true;
};
Set.prototype.some = function some(f) {
for (var v of this) if (f(v)) return true;
return false;
};
Prenons un petit ensemble
let s = new Set([1,2,3,4]);
Et quelques petites fonctions stupides
const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;
Et voyez comment ils fonctionnent
s.map(times10); //=> Set {10,20,30,40}
s.reduce(add, 0); //=> 10
s.filter(even); //=> Set {2,4}
s.every(even); //=> false
s.some(even); //=> true
N'est-ce pas sympa? Ouais, je le pense aussi. Comparez cela à l'utilisation laide de l'itérateur
// puke
let newSet = new Set();
for (let v in s) {
newSet.add(times10(v));
}
Et
// barf
let sum = 0;
for (let v in s) {
sum = sum + v;
}
Existe-t-il un meilleur moyen d'accomplir map
et d' reduce
utiliser un Set
JavaScript?
javascript
set
ecmascript-6
reduce
Je vous remercie
la source
la source
Set
est que les ensembles ne sont pas des fonctions.var s = new Set([1,2,3,4]); s.map((a) => 42);
. Cela change le nombre d'éléments, ce quimap
n'est généralement pas censé faire. Pire encore si vous ne comparez que des parties des objets conservés, car techniquement, il n'est pas spécifié lequel vous obtiendrez.forEach
existe pour ce scénario, mais pourquoi nonreduce
alors?Réponses:
Un moyen abrégé de le faire est de le convertir en un tableau via l'opérateur de propagation ES6.
Ensuite, toutes les fonctions du tableau sont à votre disposition.
la source
Array.from
c'est que celaArray.from
fonctionne avec TypeScript. L'utilisation[...mySet]
donne l'erreur:TS2461: Type 'Set<number>' is not an array type.
@@iterator
méthode.ERROR TypeError: this.sausages.slice is not a function
Pour résumer la discussion à partir des commentaires: bien qu'il n'y ait aucune raison technique pour que set ne l' ait pas
reduce
, il n'est pas actuellement fourni et nous ne pouvons qu'espérer qu'il changera dans ES7.Quant à lui
map
, l'appeler seul pourrait violer laSet
contrainte, sa présence ici pourrait donc être discutable.Envisagez de mapper avec une fonction
(a) => 42
- cela changera la taille de l'ensemble à 1, et cela pourrait ou non être ce que vous vouliez.Si vous êtes d'accord pour violer cela parce que, par exemple, vous allez vous plier de toute façon, vous pouvez appliquer la
map
partie sur chaque élément juste avant de les transmettrereduce
, acceptant ainsi que la collection intermédiaire ( qui n'est pas un ensemble à ce stade ) soit va être réduit peut avoir des éléments en double. C'est essentiellement équivalent à la conversion en Array pour effectuer le traitement.la source
s.map(a => 42)
cela entraîneraSet { 42 }
que le résultat mappé aura une longueur différente mais qu'il n'y aura pas d'éléments "dupliqués". Peut-être mettre à jour le libellé et j'accepterai cette réponse.La cause du manque de
map
/reduce
/filter
onMap
/Set
collections semble être principalement des préoccupations conceptuelles. Si chaque type de collection en Javascript spécifie réellement ses propres méthodes itératives uniquement pour permettreau lieu de
Une alternative était de spécifier map / reduction / filter dans le cadre du protocole iterable / iterator, puisque
entries
/values
/keys
returnIterator
s. Il est cependant concevable que tous les itérables ne soient pas également «mappables». Une autre alternative était de spécifier un «protocole de collecte» distinct à cette fin.Cependant, je ne connais pas la discussion actuelle sur ce sujet à ES.
la source