JavaScriptに関するお知らせ

SINCE2019
>
【JS】mapとfilterを両方同時に使いたい時の書き方4通り

【JS】mapとfilterを両方同時に使いたい時の書き方4通り


こんにちは!エンジニアになったきっかけはブラッディ・マンデイでした。Mizutani(@sirycity)です。

今回はJavaScriptでmapとfilterを両方使いたくなった時について、4通りの書き方を比較しながら見ていきましょう。

結論

  • flatMapが使える環境ならflatMap一択
  • まとめて書きたいならreduce
  • 見やすさ重視ならmapしてからfilter
  • 速度重視ならfilterしてからmap

はじめに

今回比較する書き方4通りはこちら。

  • filterしてからmapする
  • mapしてからfilterする
  • flatMapだけを使う
  • reduceだけを使う

検証

mapとfilter両方使いたいケースって言われてもピンとこない?そうだよね。

例として今回は「都道府県一覧から県以外を除外し、かつ語尾に「知事」を付けて出力」みたいな処理にします。つまりこんな感じ。

const prefs = ['北海道', '青森県', 中略, '沖縄県']

const answer = この部分の処理を検証

console.log(answer)
// ['青森県知事', '秋田県知事', 中略 , '沖縄県知事']

県ではない東京都とか北海道が除外され、県には知事が付いて「青森県知事, 秋田県知事...」といった具合に出力されていきます。こんな処理よくするよね?しねえよ。

んで、上の例ではprefsをanswerに変換する部分で 県以外を除外(filter)知事を付ける(map) の両方を使いたいわけです。この部分をどう書くか?ってなった時に4通りくらいの書き方があるので、今からそれぞれの長所と短所を見ていきましょう。

filterしてからmapする

最初は普通にfilterとmap両方使うパターン。ただしfilterを先に行うパターンです。どうぞ。分かりやすいように行を開けてます。

const answer = prefs

  .filter(pref => pref.includes('県'))

  .map(pref => pref + '知事')

長所

わかりやすい。4つの中で一番わかりやすい。県があるやつを除外して、残ったやつに「知事」をつけるっていう処理内容と順番が合致していてとてもわかりやすい。

短所

若干二度手間感ある。pref => prefが2回出てくる所とか。あと最大で2ループする。今回のケースだと都道府県の殆どが県なので、ほぼ丸々2ループしてる。

総評

ぶっちゃけこれで良い。ちょっと二度手間感が気にならなければ...

mapしてからfilterする

次に同じくmapとfilter両方使うパターン。ただし今度はmapが先。どうぞ。

const answer = prefs

  .map(pref => (pref.includes('県') ? pref + '知事' : null))

  .filter(Boolean)

長所

filterの部分がシンプル。この書き方ならmapで何しようがfilter部分は.filter(Boolean)でおk。

短所

filterがシンプルなぶんmapが複雑。とは言っても三項演算子入るだけだけど。あとは走査の順番が直感的じゃないかも。「とりあえず全部の都道府県が対象なーでも県のやつは知事付けといてそれ以外はnull付けとけ、あっnullは除外なw」みたいな感じ。ちょっとわかりにくい。

んでもって走査が多い。さっきもほぼ丸々2ループしてたけど、こっちは完全に2ループジャスト。速度はこっちの方が遅い。まあそんな変わらんけど。

総評

filter(Boolean)はかっこいいけど、あんまり使い所はないかな?

flatMapだけを使う

ここからは1個だけ使うパターン。まずはflatMap()から。

const answer = prefs.flatMap(pref => (pref.includes('県') ? pref + '知事' : []))

長所

圧倒的タイプ量の少なさ。flatMap1個で完結。以上。それだけ。走査も1ループだけ。

短所

flatMapのせいじゃないんだけど、flatMapが最近すぎて使える環境限られるかも。

あとflatMapの return [] がfilterの return falsy と同じ意味なんだけど、そこが理解できてないとちょっとコード読みのに苦労するかも。

総評

flatMapが使える環境ならこれでおk。

reduceだけを使う

reduceだけを使うパターン。こう。

const answer = prefs.reduce(
  (pre, cur) => [...pre, ...(cur.includes('県') ? [pref + '知事'] : [])],
  [],
)

長所

基本flatMapの劣化...だけど、flatMapより使える環境が多い。 flatMapは2019だけどreduceは2015。

あと強いて言うなら、後々もっと複雑な処理になった時にreduceだと拡張が楽。reduceは自由度が高すぎる。

短所

見にくい。もうほんっとに見にくい。そして激重。このブログめっちゃreduce推しだったんだけど、もうflatMapに浮気します。

総評

みにくい

結論

flatMapを使おう。まじで。以上。



PREV
2020-07-15
【JS】辞書として使うなら配列?オブジェクト?Map?様々なパターンで比較

NEXT
2020-07-20
【CSS】pxとremどちらを使うか問題に対して感じたこと