Gibt es eine Möglichkeit zu map
/ reduce
/ filter
/ etc a Set
in JavaScript oder muss ich meine eigene schreiben?
Hier sind einige sinnvolle Set.prototype
Erweiterungen
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;
};
Nehmen wir ein kleines Set
let s = new Set([1,2,3,4]);
Und einige dumme kleine Funktionen
const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;
Und sehen, wie sie funktionieren
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
Ist das nicht schön Ja, das denke ich auch. Vergleichen Sie das mit der hässlichen Iterator-Verwendung
// puke
let newSet = new Set();
for (let v in s) {
newSet.add(times10(v));
}
Und
// barf
let sum = 0;
for (let v in s) {
sum = sum + v;
}
Gibt es eine bessere Möglichkeit, eine in JavaScript zu erreichen map
und zu reduce
verwenden Set
?
javascript
set
ecmascript-6
reduce
Danke dir
quelle
quelle
Set
ist, dass Sets keine Funktoren sind.var s = new Set([1,2,3,4]); s.map((a) => 42);
. Es ändert die Anzahl der Elemente, wasmap
normalerweise nicht der Fall ist. Noch schlimmer, wenn Sie nur Teile der aufbewahrten Objekte vergleichen, denn technisch ist nicht angegeben, welche Sie erhalten.forEach
für dieses Szenario, aber warumreduce
dann nicht?Antworten:
Eine kurze Möglichkeit besteht darin, es über den ES6-Spread-Operator in ein Array zu konvertieren.
Dann stehen Ihnen alle Array-Funktionen zur Verfügung.
quelle
Array.from
dass esArray.from
mit TypeScript funktioniert. Verwenden[...mySet]
gibt den Fehler:TS2461: Type 'Set<number>' is not an array type.
@@iterator
Methode nicht implementieren .ERROR TypeError: this.sausages.slice is not a function
Um die Diskussion von Kommentaren Fazit: während es keine technischen Gründe für Satz sind nicht hat
reduce
, ist es derzeit nicht zur Verfügung gestellt und wir können nur hoffen , dass es in ES7 ändert.Wenn Sie
map
es alleine nennen, kann dies dieSet
Einschränkung verletzen , sodass seine Anwesenheit hier möglicherweise umstritten ist.Ziehen Sie eine Zuordnung mit einer Funktion in Betracht
(a) => 42
- dadurch wird die Größe des Sets auf 1 geändert, und dies könnte das sein, was Sie wollten oder nicht .Wenn Sie damit einverstanden sind, weil Sie z. B. sowieso falten, können Sie das
map
Teil auf jedes Element anwenden, bevor Sie es übergeben,reduce
und so akzeptieren, dass die Zwischensammlung ( die zu diesem Zeitpunkt kein Set ist ) das ist reduziert werden könnte doppelte Elemente haben. Dies entspricht im Wesentlichen der Konvertierung in ein Array für die Verarbeitung.quelle
s.map(a => 42)
wird in FolgeSet { 42 }
so das abgebildete Ergebnis eine andere Länge sein wird , aber es wird nicht „dupliziert“ Elemente. Vielleicht aktualisieren Sie den Wortlaut und ich werde diese Antwort akzeptieren.Die Ursache für den Mangel an
map
/reduce
/filter
onMap
/Set
Sammlungen scheinen hauptsächlich konzeptionelle Bedenken zu sein. Sollte jeder Sammlungstyp in Javascript tatsächlich seine eigenen iterativen Methoden angeben, nur um dies zuzulassenanstatt
Eine Alternative bestand darin, map / redu / filter als Teil des iterable / iterator-Protokolls anzugeben, da
entries
/values
/keys
returnIterator
s. Es ist jedoch denkbar, dass nicht jedes iterable auch "abbildbar" ist. Eine andere Alternative bestand darin, zu diesem Zweck ein separates "Sammelprotokoll" anzugeben.Die aktuelle Diskussion zu diesem Thema bei ES kenne ich jedoch nicht.
quelle