Help us understand the problem. What is going on with this article?

ES10で追加されたflat、flatMapを使ってみた。

More than 1 year has passed since last update.

概要

遂にES10が導入されましたね!!

今回、タイトル通りES10で追加されたflat、flatMapに触れていこうと思います。
基本的には他の言語にあるflat、flatMapに近いと思いますので、
既に使ったことがある人からすれば遂に来たかって感じだと思います。
flat、flatMapに関してはMDNにも記載されていますし、
基本的には他言語とほぼ変わらないと思っていますのでコーディングがあまり慣れていない方が対象になるのではないかと思っています。

注意事項

・深夜テンションで書いていますので、適宜修正していきます。
・記事が読みにくいかもしれません。ごめんなさい。
・今回動作確認した環境がGoogle chromeで確認していますが、まだ対応していないブラウザ、エディタは多いです。
・基本的に頭が悪いので「日本語は変!!」とか「は?」ってなるかもですね。
・実業務で使っていないのでサンプルもあまり意味をなさないかもです。

flat

まずはMDNの説明を見てみましょう!!

flat() メソッドは、すべてのサブ配列の要素を指定した深さで再帰的に結合した新しい配列を生成します。

MDN(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)

です。

これ以上言う事はないですね。

ただ、JavaScriptしか触っていない方やそもそもエンジニアではなく自作サイトを作るのに触ったことがあるだけの方にとってはこれと下部に記載されているサンプルコードでは良くわからないと思いますので、解説していきたいと思います。

先ずは以下データがあると仮定します。

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];

このmatsuriの配列に対してflat()をすると
matsuriの最初の配列の中にいる全ての配列を1つの展開してまとめる
事ができます。

言葉では難しいと思いますので以下コード書きます。
(説明が下手なのをコードで誤魔化しています。)

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];
matsuri.flat();
// [164, 44, [85, 59, 85], "2月4日", "19歳"]

flat解説

最初の配列にいた配列は

・[164, 44, [85, 59, 85]]
・["2月4日", "19歳"]

の2つでしたので1つの配列にまとめると
・[164, 44, [85, 59, 85], "2月4日", "19歳"]
になります。

同じようなことをflatを使用せず実現すると

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];
var tempMatsuri = [];
for(var i = 0; i < matsuri[0].length; i++) {
    tempMatsuri.push(matsuri[0][i]);
}
matsuri = tempMatsuri;

と同じになると思います。
上記記述は1例をなりますので、reduceを使ったりするともっとスッキリと記述することが出来ます。
それをflat()のみで実現することが出来ます。

上記例では最初の配列には2つの配列しか無いですが、3つの配列でも、4つの配列でも。54つの配列でも同じようになります。

ネストした配列のflat

しかし、実際に使うシチュエーションではもっと複雑なパターンを扱うことのほうが多いです。

例えば先ほどのmatsuri変数だと [164, 44, [85, 59, 85]] のなかにある [85, 59, 85] の配列も1つの配列にまとめたいパターンが出てきます。
その場合、

🤔 < matsuri変数を2回flatすれば出来るから matsuri.flat().flat()かな?

って思うかも知れませんが、1回で出来る方法もあります。

先ずは答えから記述すると

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];
matsuri.flat(2);
// [164, 44, 85, 59, 85, "2月4日", "19歳"]

です。

違いはflatの丸括弧に数字を書いてあげます

今回flat(2)としたので、
最初の配列にある全ての配列でその中にも配列があれば展開する
となります。

これを見て
🤔 < flat()に渡している数字が何で1じゃないの?
って思った方は鋭いですね。素晴らしいです。

flat(1)ではないのはflat()とflat(1)は同じ意味だからです。

つまり丸括弧の中に書いた数字分だけ配列の中の配列の中の配列の中の・・・中の配列を展開して1つの配列にまとめることが出来ます。

flatMap

先ほどflatの説明をしましたが、実際には

🤔 < 配列を展開するときに処理みたいんだけど、flatで一回展開してからじゃないとだめなの?

って思う方がいると思います。

その時にflatMapを使うんです。

今回もまずはMDNの説明を見てみましょう!!

flatMap() メソッドは、最初にマッピング関数を使用してそれぞれの要素をマップした後、結果を新しい配列内にフラット化します。
これは深さ 1 の flat が続く map と同じですが、flatMap はしばしば有用であり、2 つのメソッドを 1 つにマージするよりもやや効果的です。

MDN(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap)

です。

🤔 < は?

今回もサンプルを書いてみましょう。
まずは以下データがあります。

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];

これデータを以下の形に加工します。

javascript
var matsuri = [
    {
        "height": 164,
        "weight": 44,
        "bust": 85,
        "waist": 85,
        "hip": 85,
    },
    {
        "birthday": "2月4日",
        "age": "19歳"
    }
};

実現するソースコードです。

javascript
var matsuri = [
    [164, 44, [85, 59, 85]],
    ["2月4日", "19歳"]
];

matsuri.flatMap(function(value, index) {
    if(index === 0){
        return {
            "height":   value[0],
            "weight":   value[1],
            "bust":     value[2][0],
            "waist":    value[2][1],
            "hip":      value[2][2],
        }
    } else {
        return {
            "birthday": value[0],
            "age":      value[1]
        }
    }
})

*今回は慣れていない方にもわかりやすいようしているつもりなので、
アロー演算子や三項演算子は使っていません。

flatMap解説

まずflatMapとは上記説明したflatと配列を順番に処理するmapの機能が組み合わさったものです。

matsuri変数は配列でその中には2つの配列がいます。
mapは配列の要素分ループしますので、matsuri変数では2回ループします。

1回目のLoopは
・value => [164, 44, [85, 59, 85]]
・index => 0

2回目のLoopは
・value => ["2月4日", "19歳"]
・index => 1

なります。

flatMapの戻り値はmapと同じで配列になりますので各配列の要素に加工したデータが入ります。

後は少しでも何かしらのコードを書いた事あるならわかると思います。

解説終わり!!

あとがき

いかがだったでしょうか?
深夜テンションの勢いで書いたので結構読みずらいと思います。(深夜2時)
指摘や編集リクエストは受け付けていますので、気になった部分があればお気軽にどうぞ!!
コードの内容は勿論、日本語の添削でも嬉しいです。
まだ導入されたばかりなのでvscodeでも現状使えなかったのです。(2019年8月16日)
まだ実用的ではないので予習的に見てもらっても良いともいます。
MDNでも書いてますがIEでは使えないみたいです。(未確認)
早くIEは・・・

勿論trimStartやtrimEnd、Object.fromEntriesと言った機能も追加されていますのでこの調子でjavaScriptが盛り上がってほしいですね!!
まだ、編集中の記事がいくつもあるのでいいねを下さるとモチベ向上となります。
お手数でなければポチッとしていただけると嬉しいです。

個人的にはTypeScriptタイプセーフ過激派なので、Optional ChainingやPipeline Operatorを期待していましたが、
今回は見送りっぽいので残念です!!
ぜひes11で!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした