簡體   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