Wie würdest du das machen? Instinktiv möchte ich tun:
var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
// wishful, ignorant thinking
var newMap = myMap.map((key, value) => value + 1); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
Ich habe nicht viel aus der Dokumentation zum neuen Iterationsprotokoll gelernt .
Ich kenne wu.js , aber ich führe ein Babel- Projekt durch und möchte Traceur nicht einbeziehen , von dem es anscheinend derzeit abhängt .
Ich weiß auch nicht , wie ich fitzgen / wu.js in mein eigenes Projekt einbauen soll .
Würde eine klare, prägnante Erklärung dessen lieben, was ich hier vermisse. Vielen Dank!
Dokumente für ES6 Map , FYI
javascript
ecmascript-6
neezer
quelle
quelle
Array.from
?map
Funktion für die Verwendung auf iterables mit schreibenfor of
.Antworten:
Es
.map
selbst bietet also nur einen Wert, der Ihnen am Herzen liegt ... Es gibt jedoch einige Möglichkeiten, dies anzugehen:// instantiation const myMap = new Map([ [ "A", 1 ], [ "B", 2 ] ]); // what's built into Map for you myMap.forEach( (val, key) => console.log(key, val) ); // "A 1", "B 2" // what Array can do for you Array.from( myMap ).map(([key, value]) => ({ key, value })); // [{key:"A", value: 1}, ... ] // less awesome iteration let entries = myMap.entries( ); for (let entry of entries) { console.log(entry); }
Beachten Sie , ich bin in diesem zweiten Beispiel eine Menge neuer Sachen mit ... ...
Array.from
nimmt jede iterable (jedes Mal , wenn Sie verwenden würden[].slice.call( )
, sowie Sets und Maps) und wandelt es in ein Array ... ... Karten Wenn Sie zu einem Array gezwungen werden, verwandeln Sie sich in ein Array von Arrays, wobeiel[0] === key && el[1] === value;
(im Grunde genommen in demselben Format, mit dem ich meine Beispielkarte oben vorgefüllt habe).Ich verwende die Destrukturierung des Arrays an der Argumentposition des Lambda, um diese Array-Spots Werten zuzuweisen, bevor ich für jedes el ein Objekt zurückgebe.
Wenn Sie Babel in der Produktion verwenden, müssen Sie Babels Browser-Polyfüllung verwenden (die "core-js" und Facebooks "regenerator" enthält).
Ich bin mir ziemlich sicher, dass es enthält
Array.from
.quelle
Array.from
um das zu tun. Ihr erstes Beispiel gibt übrigens kein Array zurück..forEach
kehrtundefined
die ganze Zeit aufforEach
Hochtouren zurück , da die erwartete Verwendung von eine einfache, auf Nebenwirkungen basierende Iteration ist (wie seit ES5). Um dies zu verwenden,forEach
möchten Sie ein Array erstellen und von HandforEach
füllen , entweder über diesen oder über den von.entries()
oder.keys( )
oder zurückgegebenen Iterator.values( )
.Array.from
macht nichts Verrücktes, sondern verbirgt nur die besondere Hässlichkeit, diese Durchquerung zu machen. Und ja, überprüfenbabel-core/browser.js
Sie,.from
Array.from
nimmt eine Kartenfunktion als Parameter, Sie müssen kein temporäres Array erstellen, nur um es zuzuordnen und zu verwerfen.const obj = { x: 1 };
, wenn Sie einen Code - Block zu schreiben, schreiben Sieif (...) { /* block */ }
, wenn Sie einen Pfeil Funktion schreiben Sie schreiben() => { return 1; }
, so wie weiß es , wenn es eine Funktion Körper, im Vergleich zu der Streben eines Objekts? Und die Antwort sind Klammern. Andernfalls wird erwartet, dass der Name eine Bezeichnung für einen Codeblock ist, ein selten verwendetes Feature. Sie können jedoch eineswitch
oder eine Schleife beschriften , damit Siebreak;
sie nach Namen entfernen können . Wenn es fehlt, haben Sie einen Funktionskörper mit einer Bezeichnung und der Anweisung1
, basierend auf dem MDN-BeispielSie sollten einfach den Spread-Operator verwenden :
var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newArr = [...myMap].map(value => value[1] + 1); console.log(newArr); //[2, 3, 4] var newArr2 = [for(value of myMap) value = value[1] + 1]; console.log(newArr2); //[2, 3, 4]
quelle
Array.from
, FYI.[...myMap].map(mapFn)
wird ein temporäres Array erstellt und dann verworfen.Array.from
nimmt amapFn
als zweites Argument, benutze das einfach.Array.from(myMap.values(), val => val + 1);
?Einfach benutzen
Array.from(iterable, [mapFn])
.var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newArr = Array.from(myMap.values(), value => value + 1);
quelle
Array.from()
eine Zuordnungsfunktion als optionalen zweiten Parameter verwendet habe.Sie können diese Funktion verwenden:
function mapMap(map, fn) { return new Map(Array.from(map, ([key, value]) => [key, fn(value, key, map)])); }
Verwendung:
var map1 = new Map([["A", 2], ["B", 3], ["C", 4]]); var map2 = mapMap(map1, v => v * v); console.log(map1, map2); /* Map { A → 2, B → 3, C → 4 } Map { A → 4, B → 9, C → 16 } */
quelle
Mit
Array.from
Ich habe eine Typescript-Funktion geschrieben, die die Werte abbildet:function mapKeys<T, V, U>(m: Map<T, V>, fn: (this: void, v: V) => U): Map<T, U> { function transformPair([k, v]: [T, V]): [T, U] { return [k, fn(v)] } return new Map(Array.from(m.entries(), transformPair)); } const m = new Map([[1, 2], [3, 4]]); console.log(mapKeys(m, i => i + 1)); // Map { 1 => 3, 3 => 5 }
quelle
Tatsächlich können Sie
Map
nach dem Konvertieren in ein Array mit noch einen mit den Originalschlüsseln habenArray.from
. Dies ist möglich, indem ein Array zurückgegeben wird , bei dem das erste Elementkey
das transformierte und das zweite das transformierte Element istvalue
.const originalMap = new Map([ ["thing1", 1], ["thing2", 2], ["thing3", 3] ]); const arrayMap = Array.from(originalMap, ([key, value]) => { return [key, value + 1]; // return an array }); const alteredMap = new Map(arrayMap); console.log(originalMap); // Map { 'thing1' => 1, 'thing2' => 2, 'thing3' => 3 } console.log(alteredMap); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
Wenn Sie diesen Schlüssel nicht als erstes Array-Element zurückgeben, verlieren Sie Ihre
Map
Schlüssel.quelle
Ich ziehe es vor, die Karte zu erweitern
export class UtilMap extends Map { constructor(...args) { super(args); } public map(supplier) { const mapped = new UtilMap(); this.forEach(((value, key) => mapped.set(key, supplier(value, key)) )); return mapped; }; }
quelle
Sie können myMap.forEach verwenden und in jeder Schleife map.set verwenden, um den Wert zu ändern.
myMap = new Map([ ["a", 1], ["b", 2], ["c", 3] ]); for (var [key, value] of myMap.entries()) { console.log(key + ' = ' + value); } myMap.forEach((value, key, map) => { map.set(key, value+1) }) for (var [key, value] of myMap.entries()) { console.log(key + ' = ' + value); }
quelle
const mapMap = (callback, map) => new Map(Array.from(map).map(callback)) var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newMap = mapMap((pair) => [pair[0], pair[1] + 1], myMap); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
quelle
Wenn Sie nicht vorher die gesamte Map in ein Array konvertieren und / oder Schlüsselwert-Arrays zerstören möchten, können Sie diese dumme Funktion verwenden:
/** * Map over an ES6 Map. * * @param {Map} map * @param {Function} cb Callback. Receives two arguments: key, value. * @returns {Array} */ function mapMap(map, cb) { let out = new Array(map.size); let i = 0; map.forEach((val, key) => { out[i++] = cb(key, val); }); return out; } let map = new Map([ ["a", 1], ["b", 2], ["c", 3] ]); console.log( mapMap(map, (k, v) => `${k}-${v}`).join(', ') ); // a-1, b-2, c-3
quelle
Map.prototype.map = function(callback) { const output = new Map() this.forEach((element, key)=>{ output.set(key, callback(element, key)) }) return output } const myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]) // no longer wishful thinking const newMap = myMap.map((value, key) => value + 1) console.info(myMap, newMap)
Hängt von Ihrer religiösen Leidenschaft ab, wenn Sie vermeiden, Prototypen zu bearbeiten, aber ich finde, dass ich dies intuitiv halten kann.
quelle
Sie können () Arrays zuordnen, für Maps gibt es jedoch keine solche Operation. Die Lösung von Dr. Axel Rauschmayer :
Beispiel:
let map0 = new Map([ [1, "a"], [2, "b"], [3, "c"] ]); const map1 = new Map( [...map0] .map(([k, v]) => [k * 2, '_' + v]) );
führte zu
{2 => '_a', 4 => '_b', 6 => '_c'}
quelle
Vielleicht so:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map((k, v) => [k, v * 2]); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Sie müssten nur
Map
vorher einen Affen-Patch ausführen:Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => func(k, v))); }
Wir hätten eine einfachere Form dieses Patches schreiben können:
Map.prototype.map = function(func){ return new Map(Array.from(this, func)); }
Aber wir hätten uns gezwungen zu schreiben
m.map(([k, v]) => [k, v * 2]);
was mir etwas schmerzhafter und hässlicher erscheint.Nur Werte zuordnen
Wir könnten auch nur Werte zuordnen, aber ich würde nicht raten, diese Lösung zu wählen, da sie zu spezifisch ist. Trotzdem kann es gemacht werden und wir hätten die folgende API:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map(v => v * 2); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Genau wie vor dem Patchen auf diese Weise:
Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => [k, func(v)])); }
Vielleicht können Sie beides haben, indem Sie das zweite benennen
mapValues
, um zu verdeutlichen, dass Sie das Objekt nicht tatsächlich so zuordnen, wie es wahrscheinlich zu erwarten wäre.quelle