Bagaimana Anda melakukan ini? Secara naluriah, saya ingin melakukan:
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 }
Saya belum mengumpulkan banyak dari dokumentasi tentang protokol iterasi baru .
Saya mengetahui wu.js , tetapi saya menjalankan proyek Babel dan tidak ingin menyertakan Traceur , yang tampaknya saat ini bergantung padanya .
Saya juga sedikit tidak mengerti bagaimana cara mengekstrak bagaimana fitzgen / wu.js melakukannya ke dalam proyek saya sendiri.
Akan sangat menyukai penjelasan yang jelas dan ringkas tentang apa yang saya lewatkan di sini. Terima kasih!
Docs untuk Peta ES6 , FYI
javascript
ecmascript-6
neezer
sumber
sumber
Array.from
?map
fungsi Anda sendiri untuk digunakan di iterable, menggunakanfor of
.Jawaban:
Jadi
.map
itu sendiri hanya menawarkan satu nilai yang Anda pedulikan ... Meskipun demikian, ada beberapa cara untuk mengatasi ini:// 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); }
Perhatikan, saya menggunakan banyak hal baru dalam contoh kedua itu ... ...
Array.from
mengambil iterable (kapan pun Anda akan menggunakan[].slice.call( )
, ditambah Set dan Maps) dan mengubahnya menjadi sebuah array ... ... Maps , ketika dipaksa menjadi sebuah array, berubah menjadi array dari array, di manael[0] === key && el[1] === value;
(pada dasarnya, dalam format yang sama yang saya isi sebelumnya dengan contoh Map, di atas).Saya menggunakan destrukturisasi array dalam posisi argumen lambda, untuk menetapkan tempat array tersebut ke nilai, sebelum mengembalikan objek untuk setiap el.
Jika Anda menggunakan Babel, dalam produksi, Anda akan perlu menggunakan polyfill browser Babel (yang menyertakan "core-js" dan "regenerator" Facebook).
Saya cukup yakin itu berisi
Array.from
.sumber
Array.from
melakukan ini. Contoh pertama Anda tidak mengembalikan larik, btw..forEach
kembaliundefined
datar, sepanjang waktu, karena penggunaan yang diharapkan dariforEach
adalah iterasi berbasis efek samping sederhana (sama seperti sejak ES5). Untuk menggunakannyaforEach
, Anda ingin membangun sebuah array dan mengisinya dengan tangan, baik melalui kataforEach
atau melalui iterator yang dikembalikan oleh.entries()
atau.keys( )
atau.values( )
.Array.from
tidak melakukan sesuatu yang benar-benar unik, itu hanya menyembunyikan keburukan tertentu dari melakukan traversal tersebut. Dan ya, periksa dengan memasukkanbabel-core/browser.js
(atau apa pun itu) yang Anda dapatkan.from
...Array.from
mengambil fungsi peta sebagai param, Anda tidak perlu membuat array sementara hanya untuk memetakannya dan membuangnya.const obj = { x: 1 };
, ketika Anda menulis blok kode, Anda menulisif (...) { /* block */ }
, ketika Anda menulis fungsi panah yang Anda tulis() => { return 1; }
, jadi bagaimana ia tahu kapan itu adalah badan fungsi, versus tanda kurung dari suatu objek? Dan jawabannya adalah tanda kurung. Jika tidak, ia mengharapkan bahwa nama adalah label untuk blok kode fitur yang jarang digunakan, tetapi Anda dapat memberi labelswitch
atau loop, sehingga Anda dapatbreak;
keluar dari mereka dengan nama. Jadi jika tidak ada, Anda memiliki badan fungsi, dengan label, dan pernyataan1
, berdasarkan contoh MDNAnda hanya harus menggunakan operator Spread :
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]
sumber
Array.from
, FYI.[...myMap].map(mapFn)
akan membuat array sementara dan kemudian membuangnya.Array.from
mengambilmapFn
argumen kedua, gunakan saja itu.Array.from(myMap.values(), val => val + 1);
?Gunakan saja
Array.from(iterable, [mapFn])
.var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newArr = Array.from(myMap.values(), value => value + 1);
sumber
Array.from()
mengambil fungsi pemetaan sebagai parameter opsional kedua.Map.values()
, tidak seperti Array.values () yang masih tidak: facepalm:Anda dapat menggunakan fungsi ini:
function mapMap(map, fn) { return new Map(Array.from(map, ([key, value]) => [key, fn(value, key, map)])); }
pemakaian:
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 } */
sumber
Menggunakan
Array.from
saya menulis fungsi Ketikan yang memetakan nilai: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 }
sumber
Sebenarnya Anda masih dapat memiliki a
Map
dengan kunci asli setelah mengonversi ke array denganArray.from
. Itu dimungkinkan dengan mengembalikan larik , di mana item pertama adalahkey
, dan yang kedua adalah transformasivalue
.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 }
Jika Anda tidak mengembalikan kunci itu sebagai item larik pertama, Anda kehilangan
Map
kunci.sumber
Saya lebih suka memperluas peta
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; }; }
sumber
Anda dapat menggunakan myMap.forEach, dan di setiap loop, menggunakan map.set untuk mengubah nilai.
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); }
sumber
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 }
sumber
Jika Anda tidak ingin mengonversi seluruh Map menjadi array sebelumnya, dan / atau merusak susunan nilai-kunci, Anda dapat menggunakan fungsi konyol ini:
/** * 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
sumber
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)
Bergantung pada semangat religius Anda dalam menghindari prototipe pengeditan, tetapi, menurut saya ini memungkinkan saya membuatnya tetap intuitif.
sumber
Anda bisa memetakan () array, tetapi tidak ada operasi seperti itu untuk Maps. Solusi dari Dr. Axel Rauschmayer :
Contoh:
let map0 = new Map([ [1, "a"], [2, "b"], [3, "c"] ]); const map1 = new Map( [...map0] .map(([k, v]) => [k * 2, '_' + v]) );
menghasilkan
{2 => '_a', 4 => '_b', 6 => '_c'}
sumber
Mungkin begini:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map((k, v) => [k, v * 2]); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Anda hanya perlu menambal monyet
Map
sebelumnya:Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => func(k, v))); }
Kami bisa saja menulis bentuk yang lebih sederhana dari tambalan ini:
Map.prototype.map = function(func){ return new Map(Array.from(this, func)); }
Tapi kami akan memaksa kami untuk kemudian menulis
m.map(([k, v]) => [k, v * 2]);
yang tampaknya sedikit lebih menyakitkan dan jelek bagi saya.Nilai pemetaan saja
Kami juga dapat memetakan nilai saja, tetapi saya tidak akan menyarankan solusi itu karena terlalu spesifik. Namun demikian itu bisa dilakukan dan kami akan memiliki API berikut:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map(v => v * 2); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Sama seperti sebelum menambal dengan cara ini:
Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => [k, func(v)])); }
Mungkin Anda dapat memiliki keduanya, memberi nama yang kedua
mapValues
untuk memperjelas bahwa Anda sebenarnya tidak memetakan objek seperti yang diharapkan.sumber