.map() een Javascript ES6-kaart?

Hoe zou je dit doen? Instinctief wil ik het volgende doen:

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 }

Ik heb niet veel geleerd van de documentatie over het nieuwe iteratieprotocol.

Ik ben op de hoogte van wu.js, maar ik heb een Babel-project en willen geen Traceuropnemen, die het lijkt erop dat dit momenteel afhangt van.

Ik heb ook geen idee hoe ik hoe fitzgen/wu moet extraheren .js deed hetin mijn eigen project.

Ik zou graag een duidelijke, beknopte uitleg willen van wat ik hier mis. Bedankt!


Documenten voor ES6-kaart, ter informatie


Antwoord 1, autoriteit 100%

Dus .mapzelf biedt maar één waarde die u belangrijk vindt…
Dat gezegd hebbende, zijn er een paar manieren om dit aan te pakken:

// 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);
}

Let op, ik gebruik veel nieuwe dingen in dat tweede voorbeeld…
Array.fromneemt elke iterable (elke keer dat je [].slice.call( )zou gebruiken, plus Sets en Maps) en verandert het in een array … …Maps, wanneer ze in een array worden gedwongen, veranderen in een array van arrays, waarbij el[0] === key && el[1] === value;(in principe in hetzelfde formaat als waarmee ik mijn voorbeeldkaart hierboven heb ingevuld).

Ik gebruik destructuring van de array in de argumentpositie van de lambda, om die array-spots aan waarden toe te wijzen, voordat ik voor elke el een object teruggeef.

Als je Babel in productie gebruikt, moet je de browser-polyfill van Babel gebruiken (inclusief “core-js” en Facebook’s “regenerator”).
Ik ben er vrij zeker van dat het Array.frombevat.


Antwoord 2, autoriteit 41%

Gebruik gewoon Spread-operator:

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]

Snippet uitvouwen


Antwoord 3, autoriteit 40%

Gebruik gewoon Array.from(iterable, [mapFn]).

var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
var newEntries = Array.from(myMap, ([key, value]) => [key, value + 1]);
var newMap = new Map(newEntries);

Antwoord 4

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 }

Snippet uitvouwen


Antwoord 5

Als je niet de hele kaart vooraf in een array wilt converteren en/of key-value arrays wilt destructureren, kun je deze gekke functie gebruiken:

/**
 * 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

Snippet uitvouwen


Antwoord 6

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)

Afhankelijk van je religieuze ijver om het bewerken van prototypes te vermijden, maar ik merk dat ik het hierdoor intuïtief kan houden.


Antwoord 7

In typoscript, voor het geval iemand het nodig heeft:

export {}
declare global {
    interface Map<K, V> {
        map<T>(predicate: (key: K, value: V) => T): Map<V, T>
    }
}
Map.prototype.map = function<K, V, T>(predicate: (value: V, key: K) => T): Map<K, T> {
    let map: Map<K, T> = new Map()
    this.forEach((value: V, key: K) => {
        map.set(key, predicate(value, key))
    })
    return map
}

Antwoord 8

Misschien op deze manier:

const m = new Map([["a", 1], ["b", 2], ["c", 3]]);
m.map((k, v) => [k, v * 2]); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }

Je hoeft alleen maar patch Mapte patchen voordat:

Map.prototype.map = function(func){
    return new Map(Array.from(this, ([k, v]) => func(k, v)));
}

We hadden een eenvoudigere vorm van deze patch kunnen schrijven:

Map.prototype.map = function(func){
    return new Map(Array.from(this, func));
}

Maar we zouden ons hebben gedwongen om m.map(([k, v]) => [k, v * 2]);te schrijven, wat een beetje pijnlijker en lelijker lijkt voor mij.

Alleen toewijzingswaarden

We kunnen ook alleen waarden toewijzen, maar ik zou niet adviseren om voor die oplossing te gaan, omdat deze te specifiek is.
Desalniettemin kan het worden gedaan en zouden we de volgende API hebben:

const m = new Map([["a", 1], ["b", 2], ["c", 3]]);
m.map(v => v * 2); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }

Net zoals voor het patchen op deze manier:

Map.prototype.map = function(func){
    return new Map(Array.from(this, ([k, v]) => [k, func(v)]));
}

Misschien kunt u beide gebruiken, waarbij u de tweede mapValueseen naam geeft om duidelijk te maken dat u het object niet echt in kaart brengt zoals het waarschijnlijk zou worden verwacht.

Other episodes