[英]Why no Array.prototype.flatMap in javascript?
flatMap
is incredibly useful on collections, but javascript does not provide one while having Array.prototype.map
. flatMap
在集合上非常有用,但是 javascript 在拥有Array.prototype.map
不提供。 Why?为什么?
Is there any way to emulate flatMap
in javascript in both easy and efficient way w/o defining flatMap
manually?有没有办法以简单有效的方式在 javascript 中模拟
flatMap
,而flatMap
手动定义flatMap
?
Update: Array.prototype.flatMap
made it into ES2019更新:
Array.prototype.flatMap
进入 ES2019
It is widely supported in many environments.它在许多环境中得到广泛支持。 See if it works in your browser using this snippet below -
使用以下代码段查看它是否在您的浏览器中有效 -
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 ]
"Why no Array.prototype.flatMap in javascript?" “为什么 JavaScript 中没有 Array.prototype.flatMap?”
Because programming isn't magic and every language doesn't have features/primitives that every other language has.因为编程不是魔术,而且每种语言都没有其他语言所具有的特性/原语。 What matters is JavaScript gives you the ability to define it on your own -
重要的是 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))
Or a rewrite that collapses the two loops into one -或者重写将两个循环合二为一——
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))
If you want it to extend the Array.prototype
, nothing is stopping you -如果你想让它扩展
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
has been approved by the TC39 as part of ES2019 (ES10). flatMap
已被 TC39 批准为 ES2019 (ES10) 的一部分。 You can use it like this:你可以这样使用它:
[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]
Here's my own implementation of the method:这是我自己的方法实现:
const flatMap = (f, arr) => arr.reduce((x, y) => [...x, ...f(y)], [])
I know you said you didn't want to define it yourself, but this implementation is a pretty trivial definition.我知道你说过你不想自己定义它,但这个实现是一个非常简单的定义。
There's also this from the same github page:还有来自同一个github页面的这个:
Here is a bit of shorter way using es6 spread, similiar to renaudtertrais's - but using es6 and not adding to the prototype.这是使用 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)
Would either of these help?这两个有帮助吗?
It should be noted (thanks to @ftor) that this latter "solution" suffers from "Maximum call stack size exceeded" if called on a really large (eg, 300k elements) array a
.应该注意(感谢@ftor),如果在一个非常大的(例如,300k 个元素)数组
a
上调用,后一种“解决方案”会受到“超出最大调用堆栈大小” a
。
Lodash provides a flatmap function, which to me is practically equivalent to Javascript providing it natively. Lodash提供了一个 flatmap 函数,对我来说这实际上相当于 Javascript 原生提供它。 If you're not a Lodash user, then ES6's
Array.reduce()
method can give you the same result, but you have to map-then-flatten in discrete steps.如果您不是 Lodash 用户,那么 ES6 的
Array.reduce()
方法可以为您提供相同的结果,但您必须以离散的步骤进行 map-then-flatten。
Below is an example of each method, mapping a list of integers and returning only the odds.下面是每种方法的示例,映射整数列表并仅返回几率。
Lodash:洛达什:
_.flatMap([1,2,3,4,5], i => i%2 !== 0 ? [i] : [])
ES6 Reduce: ES6 减少:
[1,2,3,4,5].map(i => i%2 !== 0 ? [i] : []).reduce( (a,b) => a.concat(b), [] )
One fairly concise approach is to make use of the Array#concat.apply
:一种相当简洁的方法是使用
Array#concat.apply
:
const flatMap = (arr, f) => [].concat.apply([], arr.map(f)) console.log(flatMap([1, 2, 3], el => [el, el * el]));
I did somthing like this:我做了这样的事情:
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]
We now have a flatMap()
in Javascript!我们现在在 Javascript 中有一个
flatMap()
! And it is supported pretty well它得到了很好的支持
The flatMap() method first maps each element using a mapping function, then flattens the result into a new array.
flatMap() 方法首先使用映射函数映射每个元素,然后将结果展平到一个新数组中。 It is identical to a map() followed by a flat() of depth 1
它等同于 map() 后跟深度为 1 的 flat()
const dublicate = x => [x, x]; console.log([1, 2, 3].flatMap(dublicate))
Array.prototype.flatMap()
has now arrived in JS. Array.prototype.flatMap()
现在已经在 JS 中出现了。 However, not all browser might support them check for the current browser compatibility the Mozilla web docs .但是,并非所有浏览器都支持它们,请检查Mozilla 网络文档中的当前浏览器兼容性。
What the flatMap()
method does is first maps each element using a callback function as argument, then flattens the result into a new array (the 2d array is now 1d since the elements are flattened out). flatMap()
方法首先使用回调函数作为参数映射每个元素,然后将结果展平到一个新数组中(二维数组现在是 1d,因为元素被展平了)。
Here is also an example of how to use the function:这里还有一个如何使用该函数的示例:
let arr = [[2], [4], [6], [8]] let newArr = arr.flatMap(x => [x * 2]); console.log(newArr);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.