[英]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.