.map() a Javascript ES6 Map?

182

你会如何做这件事呢?本能地,我想要做:

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 }

我从新迭代协议的文档中收获不多。

我知道wu.js,但我正在运行一个Babel项目,不想包含Traceur,因为它似乎目前依赖于Traceur

我也不太清楚如何提取fitzgen/wu.js是如何做到这一点的并应用到我的项目上。

希望能有一个清晰、简洁的解释来弥补我在这方面的缺失。谢谢!


ES6 Map 的文档,供参考。


你能使用 Array.from 吗? - Ry-
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - neezer
好的,你可以编写自己的 map 函数,用于迭代器,并使用 for of - Ry-
有点挑剔,但如果你真的要在 Map 上进行“映射”,那么最终你会得到一个 Map。否则,你只是先将 Map 转换为 Array,然后再在 Array 上进行映射,而不是在 Map 上使用 .map()。你可以很容易地通过使用 ISO:dimap(x=>[...x], x=> new Map(x)) 在 Map 上进行映射。 - Dtipson
@Ry 嗯,我们可能可以编写自己的编程语言,但为什么要这样做呢?这是一个非常简单的事情,在大多数编程语言中已经存在了几十年。 - ruX
@ruX:区别在于“编写自己的map”是一个实际的选项(这也是在Array.prototype.map出现之前人们为数组所做的),而“编写自己的编程语言”则不太实际。很抱歉,JavaScript没有从可迭代对象到可迭代对象的map。你想让我说什么? - Ry-
15个回答

1

这里是一种基于现有思想并试图在以下方面灵活的TypeScript变体:

  • 输出映射的键和值类型都可以与输入不同
  • 如果需要,映射函数可以访问输入映射本身
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)))
}

注意:此代码使用了扩展运算符,就像一些现有的想法一样,因此根据我的VS Code智能感知,需要一个目标为'es2015'或更高的版本。

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

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


0

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 }


0
如果您不想事先将整个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


-1
也许可以这样实现:
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命名,以明确你实际上并没有像预期的那样映射对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接