flatMap のご紹介

こんにちは、はじめまして。
システム開発一部の寺田です。

IE11 サポート終了と ES6

半年ほど前になりますが、
Windows 10 における Internet Explorer 11 のサポートが2022年6月16日で終了となりました。
マネックス証券においても、 推奨環境より IE11 を除外させていただきました。

IE11が除外されたされたことで Chrome, Firefox, Safari そして Edge と、
ES6をサポートするモダンブラウザがフロントエンド開発のベースラインとなりました。
そこで、最初はとっつきにくいのですが理解すると便利な flatMap をご紹介いたします。

flatMap と 各種配列操作

flatMap は ES2019(ES10) で追加された配列操作メソッドです。
map, filter, reduce は ES5 で追加されたため、レガシーな環境でも概ね各種配列操作を利用できますが、
少し間をおいてから flatMap は追加されました。

説明のためレガシーな配列操作についておさらいします。
メソッド名と処理内容が概ね一致しているためすんなり理解できるかと思います。

map -> 要素の操作

let array = [1, 2, 3, 4, 5];
array = array.map((n) => {
    return n * 2;
});
console.log(array);    // -> [2, 4, 6, 8, 10]

filter -> 要素の削除

let array = [1, 2, 3, 4, 5];
array = array.filter((n) => {
    return (n % 2 != 0);
});
console.log(array);    // -> [1, 3, 5]

reduce -> 要素の集約

let array = [1, 2, 3, 4, 5];
let sum = array.reduce((prev, n) => {
    return prev + n;
}, 0);
console.log(sum);    // -> 15

flatMap

各種リファレンスには map の適用後に flat を行い配列のネストを解除すると、
簡単に説明されていることが多いのですが、実際には説明から受ける印象よりもより豊かな表現力を持つ処理となります。
上記で説明した map での要素の操作や、filter での要素の削除ができ、
filter ではできない要素の追加も行うことができます。

使用方法1 -> 要素の操作と削除(filter + map)

let array = [1, 2, 3, 4, 5];
array = array.flatMap((n) => {
    return (n % 2 != 0) ? [2 * n] : [];
});
console.log(array);    // -> [2, 6, 10]

使用方法2 -> 要素の操作と追加

let array = [1, 2, 3, 4, 5];
array = array.flatMap((n) => {
    return [2 * n - 1, 2 * n];
});
console.log(array);    // -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

使用方法3 -> flatMap のコールバック

flatMap のコールバック処理には map や filter を使うことができます。
map でも同じことができそうなのですが、戻り値が配列の配列となってしまいます。

let array = [1, 2, 3, 4, 5];
let f = (x) => {
    return [x].filter(n => n != 3).map(n => 2 * n).map(n => n - 1);
};
console.log(array.flatMap(f));    // -> [1, 3, 7, 9]
console.log(array.map(f));        // -> [[1], [3], [], [7], [9]]

使用方法4 -> 入れ子データ

HTML 文書の DOM はタグの中にタグを記載する入れ子構造をしています。
このような入れ子となっているデータと flatMap は相性がいいです。
特定のタグを取得する場合 querySelector で通常は十分なのですが、
コメント( <!--, --> )には対応していないため取得する処理を書いてみます。

let extract = (node) => {
    if(node.childNodes.length == 0){
        return node.nodeType == Node.COMMENT_NODE ? node : [];
    }
    return [...node.childNodes].flatMap(n => extract(n));
};
console.log(extract(document));    // -> [comment, comment, ...]

まとめ

flatMap をご紹介させていただきました。
flatMap を用いた処理の分かりやすさと表現力のバランスが個人的には気に入っています。

以前、Babel の紹介記事がありましたが、
今回ご紹介したコードは flatMap 以外にアロー関数やスプレッド構文など ES6 以降の機能を使っており、
トランスパイルすることなくほとんどのブラウザで動作します。

blog.tech-monex.com

証券システムというと保守的と思われがちですが、
フロントエンド開発の制約が一つ減り環境は整いつつあるかと思います。

マネックスグループの採用にご興味のある方は、ぜひ以下募集をご覧ください。

www.monexgroup.jp