. Map()一个 Javascript ES6 Map?

你会怎么做? 出于本能,我想这么做:

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 }

我没从 关于新的迭代协议的文档上收集到多少信息。

我知道 Wujs,但我正在运行一个 巴别塔项目,不想包括 Traceur,其中 似乎现在要看

我也有点不知道如何提取 Fitzgen/wujs 是怎么做到的到我自己的项目。

我想要一个清晰,简洁的解释,我在这里错过了什么。谢谢!


ES6地图的文档

152908 次浏览

所以 .map本身只提供一个您关心的值..。 也就是说,有几种方法可以解决这个问题:

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

注意,我在第二个例子中使用了很多新东西..。 ... Array.from接受任何可迭代的内容(任何时候都可以使用 [].slice.call( ),加上 Set 和 Maps)并将其转换为数组... ... Maps,当被强制转换为数组时,转换为数组的数组,其中 el[0] === key && el[1] === value;(基本上,与上面的示例 Map 预填充的格式相同)。

我在 lambda 的参数位置对数组进行解构,在为每个 el 返回一个对象之前,将这些数组点赋给值。

如果你在生产中使用 Babel,你需要使用 Babel 的浏览器 polyfill (包括“ core-js”和 Facebook 的“再生器”)。
我很确定里面有 Array.from

你应该使用 翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳:

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]

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

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 }

我使用 Array.from编写了一个类型脚本函数来映射这些值:

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 }

如果你不想事先将整个 Map 转换成一个数组,或者解构键值数组,你可以使用这个愚蠢的函数:

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

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)

这取决于你对避免编辑原型的宗教热情,但是,我发现这让我保持直观。

我更喜欢扩展地图

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

您可以映射()数组,但是对于 Maps 没有这样的操作:

  • 将 map 转换为[ key,value ]对数组。
  • 映射或筛选数组。
  • 将结果转换回映射。

例如:

let map0 = new Map([
[1, "a"],
[2, "b"],
[3, "c"]
]);


const map1 = new Map(
[...map0]
.map(([k, v]) => [k * 2, '_' + v])
);

导致

{2 => '_a', 4 => '_b', 6 => '_c'}

实际上,在使用 Array.from转换为数组之后,仍然可以使用原始键获得 Map。这可以通过返回一个 数组来实现,其中第一个项目是 key,第二个项目是转换后的 value

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 }

如果不将该 钥匙作为第一个数组项返回,则会丢失 Map键。

您可以使用 myMap.foreach,并在每个循环中使用 map.set 来更改值。

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

你可以使用这个函数:

function mapMap(map, fn) {
return new Map(Array.from(map, ([key, value]) => [key, fn(value, key, map)]));
}

用途:

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

也许这样:

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

你只需要猴子补丁 Map之前:

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

我们本可以写一个更简单的补丁:

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

但是我们会强迫我们然后写 m.map(([k, v]) => [k, v * 2]);这似乎有点更痛苦和丑陋的对我来说。

仅映射值

我们也可以只映射值,但我不建议使用这种解决方案,因为它太具体了。 然而,这是可以做到的,我们将有以下 API:

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

就像以前这样修补:

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

也许您可以两者兼备,命名第二个 mapValues,以清楚地表明您实际上并没有像预期的那样映射对象。

打字稿,以防有人需要:

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
}

下面是一个类型脚本的变体,它基于一些现有的想法,并尝试在以下方面保持灵活性:

  • 输出映射的键和值类型都可以与输入不同
  • 如果需要,mapper 函数可以访问输入映射本身
function mapMap<TKI, TVI, TKO, TVO>(map: Map<TKI, TVI>,
f: (k: TKI, v: TVI, m: Map<TKI, TVI>) => [TKO, TVO]) : Map<TKO, TVO>{
return new Map([...map].map(p => f(p[0], p[1], map)))
}

注意: 这段代码使用了扩展运算符,就像现有的一些想法一样,因此需要一个目标 of 'es2015' or higher根据我的 VS 代码智能感知。