![](/img/trans.png)
[英]Array.prototype.flatMap() JS is behaving strangely in test cases and a repl.it snippet, but not in browser console
[英]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)], [])
我知道你说过你不想自己定义它,但这个实现是一个非常简单的定义。
还有来自同一个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()
现在已经在 JS 中出现了。 但是,并非所有浏览器都支持它们,请检查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.