🥿
[JS / TS]flatMapっていつ使うん?
はじめに
コードレビューをしてもらった時に、flatMap()
ってこういう時に使えるのか!
っとなった時のメモ
flatMapとは?
flatMap メソッドは、map の後に深さ 1 の flat を呼び出すのと同じです。
flatMap()
は上記の通り、map()
とflat()
を組み合わせたメソッドです。
それぞれ軽く見てみると、
- map()
- 各要素に対して一度ずつ呼び出して処理
- 処理結果を新しい配列として返却
- flat()
- 配列の要素を指定した深さ(ネスト)で結合
- 結合した新しい配列を返却。
むむ?
map()
はさておき、flat()
がわかりづらい、、
実装例を見てみると
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]
のように、配列のネスト具合を浅くするメソッドのようです。
つまり、上記をまとめると
- 配列の各要素に対して処理して
- 処理結果のネストを浅くした配列を返す
のがflatMap()
ということになります。
配列のネストを浅くする、、?
使い所がパッとイメージできないです、、
こんな時に使えるかも!
前述の通り、(私の場合は)flatMap()
の使い所がイマイチ掴めず、後回しの対象になってました。
が、レビューで頂いた実装を見て、
「flatMapさんバカにしてすみません、、」
となりました。
要素の抽出
flatMap()
さんは、配列やオブジェクトの要素を抽出する時に、非常に便利に使えるメソッドです。
下記の例では、stringまたはnumber型の配列から、number型の値のみ抽出しています。
type HogeType = (string | number)[];
const hoge: HogeType = ["aaa", "bbb", 111, 222];
const mapResult = hoge.map((v) => (typeof v === "number" ? v : [])); // [[], [], 111, 222]
const flatMapResult = hoge.flatMap((v) => (typeof v === "number" ? v : [])); // [111, 222]
オブジェクトの場合は下記の感じです。
type HogeType = {
a: string;
b: string;
c: number;
d: number;
};
const hoge: HogeType = { a: "aaa", b: "bbb", c: 111, d: 222 };
const mapResult = Object.values(hoge).map((v) => (typeof v === "number" ? v : [])); // [[], [], 111, 222]
const flatMapResut = Object.values(hoge).flatMap((v) => (typeof v === "number" ? v : [])); // [111, 222]
ポイントは、条件に当てはまらない場合は[]
を返すところです。
これにより、.map()
で [[], [], 111, 222]
となったものが、
.flat()
の処理で空配列が削除され[111, 222]
が抽出される仕組みです。
まとめ
-
.flatMap()
は.map()
+.flat()
した処理である -
.flatMap()
は、条件に当てはまらない場合は[]
を返すことで、値の抽出ができる
具体的に「こういう場面で使える!」という選択肢が増えると、より面白さを感じられますね。
これだからプログラミングはやめられないってばよ。。
※他にもこんな使い方ができるよってものがありましたら、コメント頂けると幸いです。
参考
Discussion
zodのsafeParseとのコラボは便利かもです。
demo code.
mergeMaps関数を定義すると便利かもです。Flutterにはデフォで提供してくれているみたいです
demo code.
簡単ですが、以上です。