今回は、3種の配列メソッド、map, filter, reduceについて使い方をさらっと学ぶよ!という記事です。
近年、じわりじわりと「関数型プログラミングの時代がくるぞ…!!」と言われ続けていますので、私も波に乗ろうと勉強を始めたところ、map, filter, reduceに出会いました。
私のように、さらっと触れておきたいという方向けの記事です。
簡単に試せる(ChromeとかFirefoxならF12のコンソールに打てば結果が見れます)ので、使ったことが無い人は試してみて下さい。
map
mapを適用した配列の各要素に対して、callbackで与えた関数の処理を行った結果の配列を返却します。
return句で返却した値が、結果配列の1要素の値となります。
下記のような感じです。
[javascript] original_arr.map(callback(v, i, arr))[/javascript]
mapの使い方
mapの引数のcallback部分には、function(){}のように関数を与えます。
もちろん、アロー関数も使用できます。(mapだけでなく、filter, reduceも同様です)
functionで
[javascript] [1, 2, 3, 4, 5].map(function(v){ return v * 2; });//result=> [2, 4, 6, 8, 10] [/javascript]
アロー関数で
[javascript] [1, 2, 3, 4, 5].map(v=> v % 3 );//result=> [1, 2, 0, 1, 2] [/javascript]
もっと実践っぽく、九九表を作ってみる
こちら(Sitest.jp)で、面白そうな題材を見つけました。九九表をmapを使用して書こう!ということです。
上記ページとは異なりますが、mapを使用して下記のように書くことができます。
(ちなみに、関数指向かどうかは置いておきます。mapの使い方だけの話で)
[/javascript]
なんというか、便利です。
filter
filterを適用した配列の中から、callbackで与えた関数のreturn値がtrueとなる要素のみを抽出した新たな配列を返却します。
下記のような感じです。
[javascript] original_arr.filter(callback(v, i, arr))[/javascript]
filterの使い方
[javascript] [1, 2, 3, 4, 5].filter(v=> (v % 3) == 0 );//result=> [3] [/javascript]
filterは分かりやすい部類ですね。
引数として与えた関数の中で、結果がtrueになる要素のみを抽出するだけですね。
reduce
reduceを適用した配列に対して、隣り合う2つの要素を引数として受け取り、関数を適用、単一の値を返却します…
上手く説明できません!!
習うより慣れましょう。
下記のような書式です。
[javascript] original_arr.reduce(function(previousVal, currentVal, i, arr), initValue)[/javascript]
実際に使ってみて雰囲気を掴んで欲しいです。
reduceの使い方
まずはよくある数を足しこんでいくパターンを。
[javascript] [1, 2, 3, 4, 5].reduce((p, c)=>p + c)//result=> 15
[/javascript]
reduceの引数として渡した関数で、p(previousValue), c(currentValue)を受け取ります。
初期値(initValue)を与えていない場合、1処理目では1要素目の値がpにセットされて始まります。
初期値を与えている場合は、1処理目で初期値がpにセットされて始まります。
mapとfilterとreduceで実践っぽい処理を書いてみる
使い方は分かったけど…
[1, 2, 3, 4, 5] みたいな配列に対してmapとかfilterしても意味なくね?
もっと実践っぽい処理を書いてよ!
と言われそうなので、最後にそれっぽい処理をmap, filter, reduceを使って書いてみました。
お題は、
「Goole検索で、”Google”と検索した時の結果一覧ページから、h3タグで囲まれている見出し部分のみ(関連するキーワードみたいのは除外する)抽出して、ちょっと整形して表示する」
です。
2017/04/27現在、Googleと検索すると、下記のような検索結果になりました。
この検索結果は純粋な見出しでないもの(トップニュースの部分とか、関連するキーワードとか)も含まれているので、
(filterを使うために)除外することにしました。
(filterしなくてもquerySelectorとかで絞り込めるじゃん、なんてツッコミは受け付けません。そういう記事ですから。)
.filter(v=>v.className == "r")
.map(v=>v.textContent)
.reduce((p, c)=>p + "【"+ c + "】", "")
// result=> "【Google】
【Google のサービス | Google】
【Google マップ】
【Google ニュース】
【Google 画像検索】
【ログイン – Google アカウント – Google Accounts】
【Google】
【Google アカウントの作成 – Google Accounts】
【グーグル – ウィキペディア】
【Google – YouTube】
【Googleとは – はてなキーワード – はてなダイアリー】
"
[/javascript]
なんだか、便利っぽい雰囲気が伝わったでしょうか…
簡単に説明を書いておきますと、
1行目で、h3タグの取得結果を配列化しています。
え?getElementsByTagNameの戻り値って配列じゃ…?と思いますよね。実は違くて、HTMLCollectionらしいです…
ので、今回使用したいmapメソッドなどがありません。
仕方がないので、配列化するためにおまじないを書いています。
(詳しくは本家MDNへ⇒Array.prototype.slice())
2行目からが本番です。
filterメソッドでh3要素のうち、classNameがrのものだけを抽出します。Googleの検索結果を見ると、クラス名rが通常の検索結果見出しのようだったので。
3行目は、フィルタ結果の純粋な見出しにあたる要素配列に対して、mapメソッドを使用してテキスト部分のみを取得して新たな配列としています。
4行目は、mapで作られたstringの配列をいい感じの見た目に編集しています。
はい。今回は、以上です。