【Javascript】配列(オブジェクト)の操作【map/filter/some/reduce】
2019.10.23
プチシルバーウィークを味わったむつたくです。こんにちは。
特に行事はありませんでしたが…。
特になかったとは言え、自分にとってはAWSの勉強を出来たので有意義な休みであったことは間違い無いです!インフラも任されつつある(と思うので)こちらもアウトプットがてら、今度紹介しようかと思ってます。
即位礼正殿の儀も行われたようで、パレードは延期になってしまい残念でしたが、それ以上に恩赦対象が55万人もいる事にびっくりしています。どんな方々なんでしょうね。
さて、今回は前回に引き続いてJavaScriptの配列に於ける便利なメソッドを紹介していきます。
全部覚えて損はないメソッドになります。
やること
- map()メソッド
- filter()メソッド
- includes()メソッド
- reduce()メソッド
map()メソッド
最初に、map()メソッドから紹介します。
このmap()メソッドですが、元となる配列から新しい配列を作成するメソッドとなっています。
まずは構文を見てみましょう。
基本構文
1 2 3 | var new_array = arr.map(function callback(currentValue[, index[, array]]) { // 新しい配列の要素を返す }) |
- currentValue: 現在処理されている要素の値
- index: 現在処理されている配列(上記例では[ arr ])のインデックス
- array: map()メソッドを実行している配列(上記例では[ arr ])
map()メソッドは、元となる配列のインデックス順通りに処理していきます。
また、元になる配列には手を加えないので、変更はされません。しかし、要素がundefinedだった場合、これに対しても実行されてしまいますので、注意してください。
サンプルコード
サンプルとして、数値が格納された配列を元にして、2倍にした新しい配列を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 | const items = [1, 2, 3, 4, 5] const doubleItems = items.map( function (item) { return item * 2 }) // アロー関数の場合 const doubleItems = items.map(item => item * 2) console.log('items=>', items) console.log('doubleItems=>', doubleItems) // ***出力結果*** // items=> [1,2,3,4,5] // doubleItems=> [2,4,6,8,10] |
mapメソッドのcallback関数の引数[ item ]でitemsの要素値を取得し、2倍した結果を[ doubleItems ]にpushしているイメージになります。
自分がmap()メソッドを使うところとしては、連想配列から特定keyのvalueを取得したい時ですね。意外と便利です。for文ぐるぐる回す書き方より、1行で済みますし、可読性は上がると思われます。
例えば、こんな連想配列があるとします。
1 2 3 4 5 6 7 | const animals = [ {'id': 1, 'category': 'bird', 'name': 'sparrow'}, {'id': 2, 'category': 'bird', 'name': 'swallow'}, {'id': 3, 'category': 'dog', 'name': 'shiba'}, {'id': 4, 'category': 'bird', 'name': 'crow'}, {'id': 5, 'category': 'dog', 'name': 'poodle'} ] |
この中で、[ name ]だけを抽出した配列を作成したいとなった場合です。
そういったときは、以下のように書けば一発で出来ます。
1 2 3 4 5 | // animalsは定義済 const names = animals.map(item => item.name) console.log(names) // ***出力結果*** // [ 'sparrow', 'swallow', 'shiba', 'crow', 'poodle' ] |
似たようなメソッドで前回紹介した[ forEach ]メソッドがあります。違いは、forEach()は処理結果を返さないのに対し、map()メソッドは処理結果を返す事になります。処理結果を必要としない場合は、forEach、もしくはfor…ofを使用すると使い分けると良いと思います。
filter()メソッド
次にfilter()メソッドを紹介します。
このメソッドは名前の通り、配列の要素を絞り込み、処理結果を新しい配列として返してくれます。
指定した値だけの配列を作成したい時なんかは重宝しますね。
では、構文を見てみましょう。
基本構文
1 2 3 | var newArray = arr.filter(function callback(element[, index[, array]]) { // 絞込み条件 }) |
- element: 現在処理されている要素の値
- index: 現在処理されている配列(上記例では[ arr ])のインデックス
- array: filter()メソッドを実行している配列(上記例では[ arr ])
callback関数内で絞込みたい条件を記載し、その条件に対し、結果がtrueの場合、新しい配列にpushするイメージになります。
結果が全てfalseの場合は、空配列が作成されます。
サンプルコード
サンプルとして、指定した値より大きい数値を絞り込むコードを書きます。
1 2 3 4 5 6 7 8 9 10 11 12 | const numArray = [10, 20, 30, 40, 50] const newArray = numArray.filter( function (num) { return num > 25 }) // アロー関数の場合 const newArray = numArray.filter(num => num > 25) console.log('numArray=>', numArray) console.log('newArray=>', newArray) // ***出力結果*** // numArray=> [10, 20, 30, 40, 50] // newArray=> [30, 40, 50] |
元となる配列の要素値で25より大きい数値で新しい配列を作成しました。文字列の場合は、indexOfとかで指定文字を含んでいるものを絞り込んだりしますね。
こちらもfor文をぐるぐる回さなくて済みますし、1行で書けますので、どんどん使っていきたいところです。
もちろん、連想配列でも使用できます。
以下は、[ category ]が[ bird ]のレコードを取得したいとなった時です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const animals = [ {'id': 1, 'category': 'bird', 'name': 'sparrow'}, {'id': 2, 'category': 'bird', 'name': 'swallow'}, {'id': 3, 'category': 'dog', 'name': 'shiba'}, {'id': 4, 'category': 'bird', 'name': 'crow'}, {'id': 5, 'category': 'dog', 'name': 'poodle'} ] const birds = animals.filter(item => item.category === 'bird') console.log(birds) // ***出力結果*** // [ // { id: 1, category: 'bird', name: 'sparrow' }, // { id: 2, category: 'bird', name: 'swallow' }, // { id: 4, category: 'bird', name: 'crow' } // ] |
filter()メソッドの特徴は、一致したもの全て取得し、新しい配列を作成する事になります。
似たメソッドで、find()と言うものがあります。こちらのメソッドは、一致した最初のものを取得し、新しい配列を作成すると言う違いがあります。
1 2 3 4 5 6 | const birds = animals.find(item => item.category === 'bird') console.log(birds) // ***出力結果*** // [ // { id: 1, category: 'bird', name: 'sparrow' } // ] |
一件だけ取得したい場合は、find()メソッドを、全て取得したい場合は、filter()メソッドを、と言ったように使い分ける感じです。
includes()メソッド
次は、includes()メソッドを紹介します。
このメソッドは配列の要素に特定の値が含まれていればtrueを返してくれる便利なメソッドになります。
含まれていない場合は、falseを返します。
では、構文を見てみましょう。
基本構文
1 | arr.includes(valueToFind[, fromIndex]) |
- valueToFind: 配列内を検索する値
- fromIndex: 検索を開始するインデックス(省略時、先頭(0)から)
true/falseを返すだけですので、要素を必要としない場合に重宝するメソッドになります。
ただ、文字列を比較する場合、大文字小文字を区別しないといけないので、注意が必要です。
サンプルコード
配列の要素に「swallow」が含まれているかチェックするコードを書いていきます。
1 2 3 4 5 6 7 8 | const birds = ['sparrow', 'suwawachan', 'swallow', 'crow'] const lowerResult = birds.includes('swallow') const upperResult = birds.includes('Swallow') console.log('lowerResult=>', lowerResult) console.log('upperResult=>', upperResult) // ***出力結果*** // lowerResult=> true // upperResult=> false |
配列に対しては便利なincludes()メソッドですが、連想配列になると単純な比較ではfalseになってしまいます。
1 2 3 4 5 6 7 8 9 | const animals = [ {'id': 1, 'category': 'bird', 'name': 'sparrow'}, {'id': 2, 'category': 'bird', 'name': 'swallow'}, {'id': 3, 'category': 'dog', 'name': 'shiba'}, {'id': 4, 'category': 'bird', 'name': 'crow'}, {'id': 5, 'category': 'dog', 'name': 'poodle'} ] const result = animals.includes('swallow') // => false const result = animals.includes({'id': 2, 'category': 'bird', 'name': 'swallow'}) // => false |
そこで、連想配列に対して登場するのがsome()メソッドになります。
同じく結果をtrue/falseで返してくれます。
some()メソッドの基本構文
1 2 3 | arr.some(function callback(element[, index[, array]]) { // 比較処理 }[, thisArg]) |
- element: 現在処理されている要素
- index: 現在処理されている要素のインデックス
- array: 処理されている配列
some()メソッドのサンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | const animals = [ {'id': 1, 'category': 'bird', 'name': 'sparrow'}, {'id': 2, 'category': 'bird', 'name': 'swallow'}, {'id': 3, 'category': 'dog', 'name': 'shiba'}, {'id': 4, 'category': 'bird', 'name': 'crow'}, {'id': 5, 'category': 'dog', 'name': 'poodle'} ] const result = animals.some( function (item) { return item.name === 'swallow' }) // アロー関数の場合 const result = animals.some(item => item.name === 'swallow') console.log(result) |
some()メソッドは連想配列はもちろん、配列にも使えますので、some()メソッドに軍配が上がるかも知れません。
ただ、配列かつ、単純な比較(条件が1つ)であればincludes()メソッドにする、連想配列の場合または、配列だけど複雑な比較(条件が2つ以上)の場合は、some()メソッドにする等の使い分けはできそうです。
reduce()メソッド
次は、reduce()メソッドを紹介します。
このメソッド、すごい優秀です。今まで紹介した全てのメソッドを機能的に網羅してます。
何でもかんでもreduce()メソッドにしたら可読性が落ちるかも知れないので使い分けてますが。
reduce()メソッドですが、配列の各要素を累積して1つの値にすることができます。
では、構文を見てみましょう。
基本構文
1 2 3 | var result = arr.reduce(function callback(accumulator, currentValue[, currentIndex[, array]]) { // 処理 }[, initialValue]) |
- accumulator: callback関数の結果を累積する
- currentValue: 現在処理されている配列の要素
- currentIndex: 現在処理されている配列のインデックス
- array: reduce()メソッドを実行している配列
- initialValue: callback関数を呼び出し時に設定される値。省略すると最初の要素値が設定される
callback関数内で累積処理を記載し、累積結果を返すイメージになります。
空配列の場合、エラーが返ってきてしまうので、エラーにならないよう[ initialValue ]に開始値(デフォルト値)を設定するのも有りです。(加算する場合は、例えば0など)
サンプルコード
配列の全要素を累積した結果を表示するコードを書いていきます。
1 2 3 4 5 6 7 8 9 10 11 | const numArray = [1, 2, 3, 4, 5] const result = numArray.reduce( function (accumulator, currentValue) { return accumulator + currentValue }) // アロー関数の場合 const result = numArray.reduce( (accumulator, currentValue) => accumulator + currentValue ) console.log(result) // ***出力結果*** // 15 |
今回は加算したケースを紹介しましたが、例えば、配列内での最大値を求めることもできます。[ accumulator ]と[ currentValue ]を比較して大きい方をreturnする…とかしてしまえば、最大値を求められます。逆も然りです。
また、特定の条件に一致したものをreduce()メソッド外で宣言した配列にpushしてしまえば、その条件に一致した配列を作成できる、と言った感じで、多方面で活躍できる、優れたメソッドになります。コードが冗長になるのが欠点ですが。
まとめ
map()メソッド、filter()メソッド、includes()メソッド、reduce()メソッド。ついでにfind()メソッドとsome()メソッドも紹介しましたがいかがでしたか?
- map()メソッド … 元となる配列から新しい配列を作成するメソッド
- filter()メソッド … 配列の要素を絞り込み、一致した全ての結果を新しい配列として返す
- find()メソッド … 配列の要素を検索し、一致最初の結果を新しい配列として返す
- includes()メソッド … 配列に特定の値が含まれていればtrueを返す、無ければfalseを返す(主に配列、単純な条件時に使用)
- some()メソッド … 配列に特定の値が含まれていればtrueを返す、無ければfalseを返す(主に連想配列、複雑な条件時に使用)
- reduce()メソッド … 配列の要素を累積する(機能的に上記全てを網羅しているが、コードが冗長化する)
便利なメソッドたちなので、どんどん使用していき、冗長なコードから卒業していければ万々歳です。
コードの効率化も図れると思います。
それでは、またの機会に。
良いコーディングライフを!
↓↓↓ぜひチェックしてください
~提供中のヒューマンセンシング技術~
◆人物検出技術
歩行者・来店者数計測やロボット搭載も
https://humandetect.pas-ta.io
◆視線検出技術
アイトラッキングや次世代UIに
https://eyetrack.pas-ta.io
◆生体判定技術
eKYC・顔認証のなりすまし対策を!
https://bio-check.pas-ta.io
◆目検出技術
あらゆる目周りデータを高精度に取得
https://pupil.pas-ta.io
◆音声感情認識技術
会話から怒りや喜びの感情を判定
https://feeling.pas-ta.io
◆虹彩認証技術
目の虹彩を利用した生体認証技術
https://iris.pas-ta.io