web-dev-qa-db-ja.com

javascriptにArray.prototype.flatMapがないのはなぜですか?

flatMapはコレクションで非常に便利ですが、javascriptはArray.prototype.mapを持っている間は提供しません。どうして?

flatMapを手動で定義せずに、簡単で効率的な方法でJavaScriptでflatMapをエミュレートする方法はありますか?

54
Sergey Alaev

更新:Array.prototype.flatMap は、ネイティブECMAScriptへの道を進んでいます。現在Stage 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))

または、2つのループを1つにまとめる書き換え

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, [])

Array.prototype.flatMap = function(f) {
  return flatMap(f,this)
}

const xs = [1,2,3]

console.log(xs.flatMap(x => [x-1, x, x+1]))
63
user633183

flatMapは、ES2019(ES10)の一部としてTC39によって承認されています。次のように使用できます。

[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]

メソッドの実装は次のとおりです。

const flatMap = (f, arr) => arr.reduce((x, y) => [...x, ...f(y)], [])

flatMapのMDN記事

43
Kutyel

自分で定義したくないと言っていたことは知っていますが、 この実装 は非常に簡単な定義です。

同じgithubページからもこれがあります:

以下は、renaudtertraisに似たes6 spreadを使用した少し短い方法ですが、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で呼び出された場合、「最大呼び出しスタックサイズを超過」することに注意する必要があります。

9
Alan Mimms

Lodash はflatmap関数を提供します。これは私にとって、ネイティブに提供するJavascriptと実質的に同等です。 Lodashを使用していない場合、ES6のArray.reduce()メソッドを使用しても同じ結果を得ることができますが、個別のステップでマッピングして平坦化する必要があります。

以下は、整数のリストをマッピングし、オッズのみを返す各メソッドの例です。

Lodash:

_.flatMap([1,2,3,4,5], i => i%2 !== 0 ? [i] : [])

ES6 Reduce:

[1,2,3,4,5].map(i => i%2 !== 0 ? [i] : []).reduce( (a,b) => a.concat(b), [] )
5

かなり簡潔なアプローチの1つは、Array#concat.applyを使用することです。

const flatMap = (arr, f) => [].concat.apply([], arr.map(f))

console.log(flatMap([1, 2, 3], el => [el, el * el]));
1
JLRishe

JavascriptにflatMap()が追加されました!そして、それはサポートされています かなりうまく

FlatMap()メソッドは、まずマッピング関数を使用して各要素をマッピングし、次に結果を新しい配列にフラット化します。 map()の後に深さ1のflat()が続くのと同じです。

const dublicate = x => [x, x];

console.log([1, 2, 3].flatMap(dublicate))
0
bigInt