Javascript 高階関数を入門してみた map / filter / reduce / some / flatMap
高階関数とは?
- 引数に関数を受け取る関数のこと(正確な説明だが、初めて聞くとわけがわからない)
- 高階関数を使うと、配列を処理するときにfor文を使わなくて済む。
- let i のようなループ用変数を使わず、const変数だけでコードが書けるのが嬉しい!!
2022年現在、高階関数が分からないと時代に取り残されそうな雰囲気なので、さっそく学習を始めることにした。
map:配列の要素を変換する(マッピングする)
【例題】
日付を表す8桁の数値(例:20210819)の配列がある。
これを、日を表す数値(例:19)に変換して配列を出力せよ。
mapを使わない書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; let output = []; for(let i = 0, z = input.length; i < z; i++){ const n日 = input[i] % 100; output.push(n日); } console.log(output); // [19, 20, 30, 31, 1]
mapを使う書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; const output = input.map(elem => { const n日 = elem % 100; return n日; }); console.log(output); // [19, 20, 30, 31, 1]
filter:配列の要素を抜き出す(フィルタリングする)
【例題】
日付を表す8桁の数値(例:20210819)の配列がある。
ここから、12月の日付だけを抜き出して配列を出力せよ。
filter を使わない書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; let output = []; for(let i = 0, z = input.length; i < z; i++){ const n年月 = input[i] / 100 | 0; // YYYYMM const n月 = n年月 % 100; if(n月 === 12){ output.push(input[i]); } } console.log(output); // [20211230, 20211231]
filter を使う書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; const output = input.filter(elem => { const n年月 = elem / 100 | 0; // YYYYMM const n月 = n年月 % 100; return n月 === 12; // 12月ならtrue }); console.log(output); // [20211230, 20211231]
reduce:配列を集計して単一の値にする
【例題】
日付を表す8桁の数値(例:20210819)の配列がある。
日を表す数値(例:19)のうち、最大の数値を出力せよ。
reduce を使わない書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; let output = -1; for(let i = 0, z = input.length; i < z; i++){ const n日 = input[i] % 100; output = Math.max(n日, output); } console.log(output); // 31
reduce を使う書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; const output = input.reduce((acc, elem, i, ary) => { // 累積値・各要素・連番・配列自体 const n日 = elem % 100; return Math.max(n日, acc); }, -1); // 累積値の初期値 console.log(output); // 31
メモ
reduce内の関数は、5回実行される。return結果が次のacc(累積値)となる。
acc(累積値)・elem(各要素)・i(連番)・return結果は、以下の表のようになる。
acc(累積値) | elem(各要素) | i(連番) | return結果 |
---|---|---|---|
-1 | 20210819 | 0 | 19 |
19 | 20210820 | 1 | 20 |
20 | 20211230 | 2 | 30 |
30 | 20211231 | 3 | 31 |
31 | 20220101 | 4 | 31 |
some:ひとつでも該当すれば true を返す
【例題】
日付を表す8桁の数値(例:20210819)の配列がある。
配列の要素が昇順にソートされている場合は true、
昇順にソートされていない場合は false を出力せよ。
some を使わない書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; let output = true; for(let i = 0, z = input.length; i < z; i++){ if(i === 0){ continue; } if(input[i-1] > input[i]){ output = false; // 昇順ではない場合、false で処理終了 break; } } console.log(output); // true
some を使う書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; const output = ! input.some((elem, i, ary) => { // 各要素・連番・配列自体 if(i === 0){ return false; } return ary[i-1] > elem; // 昇順ではない場合、true で処理終了 }); console.log(output); // true
flatMap:配列の次元を下げて連結する
【例題】
日付を表す8桁の数値(例:20210819)の配列がある。
日を表す数値(例:19)の配列を出力せよ。
ただし、10日、20日、30日の場合は、2つ重複させて出力せよ。
flatMap を使わない書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; let output = []; for(let i = 0, z = input.length; i < z; i++){ const n日 = input[i] % 100; if(n日 % 10 === 0){ output.push(n日); output.push(n日); }else{ output.push(n日); } } console.log(output); // [19, 20, 20, 30, 30, 31, 1]
flatMap を使う書き方
const input = [20210819, 20210820, 20211230, 20211231, 20220101]; const output = input.flatMap(elem => { const n日 = elem % 100; if(n日 % 10 === 0){ return [n日, n日]; }else{ return [n日]; } }); console.log(output); // [19, 20, 20, 30, 30, 31, 1]