JavaScriptのmap,filterを用いた配列処理について

Tech

今回は表題の通りJavaScriptのArray.prototype.map()、Array.prototype.filter()を用いた配列処理についてお話します。

ざっくり説明すると、mapは「配列の全要素に対して指定の関数を適用した、新しい配列を返す」メソッドで、
filterは「配列の全要素に対して指定の関数を適用し、trueの要素のみ残した新しい配列を返す」メソッドとなります。
どちらも指定の関数を全要素に適用するものですが、これらのメソッド自体は「新しい配列を返す(=元の配列を変更しない)」事も大きなポイントです。

 

・map
[1, 2, 3, 4, 5].map(e => e + 10) // => [11, 12 13, 14, 15]

// こちらの例も同じ
const addTen = e => e + 10
[1, 2, 3, 4, 5].map(addTen)

 

上記は配列の全要素に10を足す関数を適用する例です。
function (現在の要素) {} のような、1要素受け取る関数を渡してやるのが基本的な使い方です。
また、mapは新しい配列を返却するので、mapをチェインして更に別の処理を加えてやることもできます。

 

type Obj = {
name: string,
postcode: string
}
const obj: Obj = {
name: ‘Alice’,
postcode: ‘1000000’
}

 

例えば、上記のような「XXXXXXX」形式の郵便番号を持つオブジェクトの配列があったとして、
そこから郵便番号だけを抜き取り、更に「〒XXX-XXXX」形式にフォーマットしたい場合は

 

const arr: Obj[] = [/* Objを要素に持つ配列 */]
const formatPostcode = e => /* 8桁の郵便番号を「〒XXX-XXXX」形式にフォーマットする関数 */
const postcodes = arr.map(e => e.postcode).map(formatPostcode)

 

のように書けます。
追加として、mapに渡す関数は省略可能な第2引数と第3引数を持てて、それぞれ「現在の配列の添字」「mapが適用されている配列そのもの」を受け取ります。
n番目の要素は違う処理をするだとか、配列の長さが見たい時だとかに使えます。

 

・filter
[1, 2, 3, 4, 5, 6].filter(e => e % 2 === 0) // => [2, 4, 6]

 

上記はfilterを適用する配列から、偶数の要素のみを抽出する例です。
`filter`が引数として受け取る関数の引数の形式(第1引数が現在の要素、省略可能な第2, 第3引数)は同じですが、
受け取る関数が真偽値(true, false)を返す必要がある点が異なります。
mapと同様新しい配列を返却するので、更にmapやfilterをチェインできます。

 

// Objの型はmapの例と同様
const arr: Obj[] = [/* Objを要素に持つ配列 */]
const arr2 = arr.filter(e => e.postcode === ‘1020072’).map(e => e.name)

 

上記は郵便番号が1020072の要素を抜き出し、さらにその要素の名前だけを残す処理の例です。

 

const isLessThanSix = e => /* 6字より少ないなら警告文を返却、そうでなければ”を返却する関数 */
const notContainsUpperCase = e => /* 大文字を含んでいなければ警告文を返却、そうでなければ”を返却する関数 */
const notContainsLowerCase = e => /* 小文字を含んでいなければ警告文を返却、そうでなければ”を返却する関数 */
const validation = text => {
return [isLessThanSix, notContainsUpperCase, notContainsLowerCase]
.map(f => f(text))
.filter(Boolean)
}
const invalidPassword = validation(‘aaaaa’) // => [‘6字より少ないときの警告文’, ‘大文字を含んでいないときの警告文’]
const validPassword = validation(‘aaaaaA’) // => []

 

もう一例、map, filterを用いたバリデーションの例です。
エラー文を返す関数を配列にして、「関数 => エラー文(または”)」にmapし、”でない要素をfilterしています。
mapを使うことで「ここは配列を変更しています」、filterを使うことで「ここは配列をフィルタリングしています」というのが明確になるので、
同様の配列処理をforで行った場合と比べ、コードが宣言的で簡潔に記述できるようになるのがポイント高いです。
今日、JavaScriptにおけるmap, filterと同様の機能は色々な言語に(名前は違えど)搭載されているので、是非使ってみてください。

 

参考:Array.prototype.map() – JavaScript | MDN – https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Array.prototype.filter() – JavaScript | MDN – https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter