flatMap
在集合上非常有用,但是javascript不能提供一个Array.prototype.map
。为什么?
有没有办法以flatMap
简单有效的方式在javascript中进行仿真,而无需flatMap
手动定义?
flatMap
在集合上非常有用,但是javascript不能提供一个Array.prototype.map
。为什么?
有没有办法以flatMap
简单有效的方式在javascript中进行仿真,而无需flatMap
手动定义?
arr.map(...).reduce(...)
)。
Answers:
更新: Array.prototype.flatMap
正在本机ECMAScript上。目前处于第4阶段。
它在许多环境中得到广泛支持。使用下面的代码片段查看它是否在您的浏览器中有效-
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((acc,x) =>
acc.concat(f(x)), [])
const xs = [1,2,3]
console.log(flatMap(x => [x-1, x, x+1], xs))
如果您想在上进行操作Array.prototype
,则没有什么可以阻止您
const concat = (x, y) => x.concat(y)
const flatMap = (f, xs) => xs.map(f).reduce(concat, [])
if (Array.prototype.flatMap === undefined) {
Array.prototype.flatMap = function(f) {
return flatMap(f, this)
}
}
const xs = [1, 2, 3]
console.log(xs.flatMap(x => [x-1, x, x+1]))
.as-console-wrapper { top: 0; max-height: 100% !important; }
Array.prototype._mylib_flatMap
)进行命名空间,甚至更好地使用ES6符号,而不是简单地定义Array.prototype.flatMap
。
map
定义为全局函数!第二只是不好的做法
append
,map
,filter
,foldl
,foldr
中无数人在默认的命名空间。这并不是一个坏习惯,因为您听说有人说“全球人是坏人”或“扩展本地人是坏人”-球拍是设计最好的语言之一。您只是不知道如何/何时适当地进行。
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)], [])
flapMap
什么?我想展平我的地图,而不是拍平它!
const flatMap = (arr, ...args) => [].concat(...arr.map(...args));
(或使用apply
您不能使用散布运算符的方法)-尽管此concat版本在
我知道您说过您不想自己定义它,但是此实现是一个非常简单的定义。
在同一个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
。
[].concat(...(new Array(300000).fill("foo").map(x => x.toUpperCase())))
。当然,这是一个极端的案例。但是您至少应该提到它。
Lodash提供了flatmap函数,对我而言,它实际上等效于Javascript本机提供的功能。如果您不是Lodash用户,那么ES6的Array.reduce()
方法可以为您提供相同的结果,但是您必须以离散的步骤进行映射然后展平。
下面是每种方法的示例,它们映射一个整数列表并仅返回几率。
Lodash:
_.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.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]
{ "message": "Uncaught TypeError: [1,2,3].flatMap is not a function", "filename": "https://stacksnippets.net/js", "lineno": 15, "colno": 23 }
Array.prototype.flatMap()
现在已经到达JS。但是,并非所有的浏览器都可能支持它们,请检查Mozilla Web文档的当前浏览器兼容性。
该flatMap()
方法的作用是,首先使用回调函数作为参数映射每个元素,然后将结果展平为新数组(由于元素被展平,因此2d数组现在为1d)。
这也是如何使用该函数的示例:
let arr = [[2], [4], [6], [8]]
let newArr = arr.flatMap(x => [x * 2]);
console.log(newArr);
arr.reduce((arr, v) => (arr.push(...v), arr), [])
吗?