繁体   English   中英

为什么javascript中没有Array.prototype.flatMap?

[英]Why no Array.prototype.flatMap in javascript?

flatMap在集合上非常有用,但是 javascript 在拥有Array.prototype.map不提供。 为什么?

有没有办法以简单有效的方式在 javascript 中模拟flatMap ,而flatMap手动定义flatMap

更新: Array.prototype.flatMap进入 ES2019

它在许多环境中得到广泛支持。 使用以下代码段查看它是否在您的浏览器中有效 -

 const data = [ 1, 2, 3, 4 ] console.log(data.flatMap(x => Array(x).fill(x))) // [ 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 ]


“为什么 JavaScript 中没有 Array.prototype.flatMap?”

因为编程不是魔术,而且每种语言都没有其他语言所具有的特性/原语。 重要的是 JavaScript 让你能够自己定义它——

 const concat = (x,y) => x.concat(y) const flatMap = (f,xs) => xs.map(f).reduce(concat, []) const xs = [1,2,3] console.log(flatMap(x => [x-1, x, x+1], xs))

或者重写将两个循环合二为一——

 const flatMap = (f, xs) => xs.reduce((r, x) => r.concat(f(x)), []) const xs = [1,2,3] console.log(flatMap(x => [x-1, x, x+1], xs))

如果你想让它扩展Array.prototype ,没有什么能阻止你 -

 if (!Array.prototype.flatMap) { function flatMap (f, ctx) { return this.reduce ( (r, x, i, a) => r.concat(f.call(ctx, x, i, a)) , [] ) } Array.prototype.flatMap = flatMap } const ranks = [ 'J', 'Q', 'K', 'A' ] const suits = [ '♡', '♢', '♤', '♧' ] const result = ranks.flatMap(r => suits.flatMap(s => [[r, s]] ) ) console.log(JSON.stringify(result)) // [ ['J','♡'], ['J','♢'], ['J','♤'], ['J','♧'] // , ['Q','♡'], ['Q','♢'], ['Q','♤'], ['Q','♧'] // , ['K','♡'], ['K','♢'], ['K','♤'], ['K','♧'] // , ['A','♡'], ['A','♢'], ['A','♤'], ['A','♧'] // ]

flatMap已被 TC39 批准为 ES2019 (ES10) 的一部分。 你可以这样使用它:

[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]

这是我自己的方法实现:

const flatMap = (f, arr) => arr.reduce((x, y) => [...x, ...f(y)], [])

关于 flatMap 的 MDN 文章

我知道你说过你不想自己定义它,但这个实现是一个非常简单的定义。

还有来自同一个github页面的这个:

这是使用 es6 扩展的一种更短的方法,类似于 renaudtertrais - 但使用 es6 而不是添加到原型中。

var flatMap = (a, cb) => [].concat(...a.map(cb))

const s = (v) => v.split(',')
const arr = ['cat,dog', 'fish,bird']

flatMap(arr, s)

这两个有帮助吗?

应该注意(感谢@ftor),如果在一个非常大的(例如,300k 个元素)数组a上调用,后一种“解决方案”会受到“超出最大调用堆栈大小” a

Lodash提供了一个 flatmap 函数,对我来说这实际上相当于 Javascript 原生提供它。 如果您不是 Lodash 用户,那么 ES6 的Array.reduce()方法可以为您提供相同的结果,但您必须以离散的步骤进行 map-then-flatten。

下面是每种方法的示例,映射整数列表并仅返回几率。

洛达什:

_.flatMap([1,2,3,4,5], i => i%2 !== 0 ? [i] : [])

ES6 减少:

[1,2,3,4,5].map(i => i%2 !== 0 ? [i] : []).reduce( (a,b) => a.concat(b), [] )

一种相当简洁的方法是使用Array#concat.apply

 const flatMap = (arr, f) => [].concat.apply([], arr.map(f)) console.log(flatMap([1, 2, 3], el => [el, el * el]));

我做了这样的事情:

Array.prototype.flatMap = function(selector){ 
  return this.reduce((prev, next) => 
    (/*first*/ selector(prev) || /*all after first*/ prev).concat(selector(next))) 
}

[[1,2,3],[4,5,6],[7,8,9]].flatMap(i => i); //[1, 2, 3, 4, 5, 6, 7, 8, 9]

[{subarr:[1,2,3]},{subarr:[4,5,6]},{subarr:[7,8,9]}].flatMap(i => i.subarr); //[1, 2, 3, 4, 5, 6, 7, 8, 9]

我们现在在 Javascript 中有一个flatMap() 它得到了很好的支持

flatMap() 方法首先使用映射函数映射每个元素,然后将结果展平到一个新数组中。 它等同于 map() 后跟深度为 1 的 flat()

 const dublicate = x => [x, x]; console.log([1, 2, 3].flatMap(dublicate))

Array.prototype.flatMap()现在已经在 J​​S 中出现了。 但是,并非所有浏览器都支持它们,请检查Mozilla 网络文档中的当前浏览器兼容性。

flatMap()方法首先使用回调函数作为参数映射每个元素,然后将结果展平到一个新数组中(二维数组现在是 1d,因为元素被展平了)。

这里还有一个如何使用该函数的示例:

 let arr = [[2], [4], [6], [8]] let newArr = arr.flatMap(x => [x * 2]); console.log(newArr);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM