JavaScript 便利な配列操作メソッド

JavaScript 便利な配列操作メソッド

今回は個人的に便利だなと感じるJavaScriptの配列操作に関するメソッドを8つピックアップしてみました。

map

MapメソッドはReactを使ってると繰り返し処理でよく使用します。

配列の各要素を変換する際に有効なメソッドです。

mapはコールバック関数内に実行したい処理を書く事で、配列の各要素を操作してその結果として新しい配列を返します

※JavaScriptは関数がファーストクラスの為、その場で作成した匿名関数(名前のない関数)を引数として渡す事が可能です。
引数として渡される関数がコールバック関数です。
コールバック関数を引数として受け取るメソッドや関数を高階関数と呼びます。
これから紹介するメソッドは全てこの高階関数になります。

const numbers = [1, 2, 3];

// コールバックでnumbers配列を2倍する処理を記述
const doubleNumbers = numbers.map(number => number * 2);

console.log(doubleNumbers); // [2, 4, 6]

// 定義した関数をmapのコールバックとして呼び出す事も可能
const twice = num => num * 2;
const doubleNumbers = numbers.map(twice);

もう一つ簡単な例を紹介します。

税込み金額(withTax)を求めるため、合計金額(total)に税率(1.1)を掛ける処理をします。

mapを使わない場合だと配列を定義してfor文でループさせてから値を入れる事になります。

mapを使うと冗長的な書き方が排除できて簡素に記述が可能になります。

const total = [20, 40, 50];

/** map未使用 */
const withTax = [];
for (let i=0; i<total.length; i++) {
  withTax.push(total[i] * 1.1);
}
console.log(withTax)


/** map使用 */
const withTax = total.map(num => num * 1.1);
console.log(withTax);

Array.prototype.map()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map

forEach

forEachは配列に対してfor文と同じように反復処理を行う事が出来ます。

配列の各要素に対して個別にコールバック関数を実行します。

const items = [
  {name: 'aa', age: 22},
  {name: 'bb', age: 23},
  {name: 'cc', age: 25},
  {name: 'dd', age: 26},
]

// 配列に格納されている各オブジェクトのプロパティにアクセスする
items.forEach(item => {
  console.log(item.name); // aa bb cc dd
})


先ほど紹介したmapメソッドと同じように配列の各要素に対してcallback関数を一度ずつ実行しますが、その違いは返り値があるかないかです。

mapの場合、処理実行後の結果を新しい配列として値が返ってきます。

それに対してforEachは返り値がundefinedになります。

const mapResult = [1, 2, 3].map(v => v*2);
const forEachResult = [1, 2, 3].forEach(v => v*2);

console.log(mapResult) // [2, 4, 6]
console.log(forEachResult) // undefined

Array.prototype.forEach()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

filter

配列の要素を順番にコールバック関数へ渡し、コールバック関数内で指定した条件にtrueを返した要素のみを集めた新しい配列を返します。

対象としているデータに対して特定の条件を与え、それに該当するデータのみを取り出したい場合に役立つメソッドです。

const price = [100, 300, 500, 700];
const over500price = price.filter(num => {
  // 500以上の数値だけを取得するよう条件指定
  return num >= 500;
})
console.log(over500price) // [500, 700]

splice

配列から不要な要素を取り除く際にはspliceメソッドを使う事も出来ます。
(spliceメソッドは他にも要素を追加、置換えする事で配列を変更することが可能です)

filterは元の配列に対して変更を加えず新しい配列を返すのに対して、spliceメソッドは元の配列も変更してしまう破壊的なメソッドです。

spliceメソッドの返り値は取り除かれた要素を含む配列です。

spliceメソッドの引数(indexが1番目の引数、howManyが2番目の引数となる)

  • index: 配列の変更を開始する位置。先頭のインデックスは0。負数の場合、末尾から数えた位置が指定される。
  • howMany: 配列から取り除く要素の数。0の場合は要素の削除は行われない。
  • 3番目以降の引数は追加する要素。
const price = [100, 300, 500, 700];
let index = price.findIndex(num => num<500);
// 当てはまる要素がない場合、findIndexの返値は-1となる
while (index !== -1) {
  price.splice(index, 1)
  index = price.findIndex(num => num<500);
}
console.log(price) // [500, 700]

let array = [1, 2, 3]
const result = array.splice(1, 1)
console.log(array) // [1, 3]

// spliceメソッドの返り値は取り除かれた要素を含む配列です。
console.log(result) // [2]

Array.prototype.filter()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://jsprimer.net/basic/array/#array-filter

reduce

reduceは配列に対して処理を順次適用していきます。

コールバック関数の引数として累積値(accumulator)、要素、インデックス、配列を持つ。
reduceメソッドの第2引数を指定する事で累積値の初期値を設定出来ます。

下記の例では初期値が設定されているので次のような処理がされます。

  • 初回実行の引数は累積値の初期値である0と先頭の要素である10になり(0, 10)、返り値は 0 + 10で10。
  • 2回目の実行の引数は前回の返り値である10と2番目の要素の20となり(10, 20)、返り値は 10 + 20で30。
  • 3回目の実行の引数は前回の返り値である30と3番目の要素の30となり(30, 30)、返り値は 30 + 30で60。
  • 全ての要素を処理したのでreduce自体の返り値は60となる。
const price = [10, 20, 30];
const totalPrice = price.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0)

console.log(totalPrice) // 60

// reduceを未使用の場合
let total = 0;
for (let i=0; i<price.length; i++) {
  total += price[i];
}
console.log(total) // 60

Array.prototype.reduce()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

find

findは配列から指定した条件に合う要素を検索して、返り値は最初の要素になります。

条件に合う要素が見つからなかった場合はundefinedが返されます。

const items = [
  {name: 'aa', price: 220},
  {name: 'bb', price: 230},
  {name: 'cc', price: 250},
  {name: 'dd', price: 260},
]
const targetElement = items.find(item => {
  return item.name === 'bb';
})
console.log(targetElement) // Object {name: "bb", price: 230}

findfilterを使用して最初の要素を取り出した場合と同じになります。

findメソッドは条件に合う最初の要素が見つかった時点で残りの要素に対して検索を行わないので、配列の要素が多い場合にはfilterよりもfindメソッドの方が高速みたいです。

const useFilterMethod = items.filter(item => {
  return item.name === 'bb';
})
// findメソッド使用時と同じ結果が得られる
console.log(useFilterMethod[0]) // Object {name: "bb", price: 230}

Array.prototype.find()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/find

some

someは配列のいずれかの要素が指定した条件を満たしているかを確認する際に使用します。

返り値は真偽値となるのでtrueもしくはfalseになります。

const array1 = [1, 2, 3, 4, 5, 6]
const array2 = [2, 4, 6]
function isOdd (num) {
  return num % 2 !==0;
}
// 配列のいずれかの要素が奇数かどうかの判定
const result1 = array1.some(isOdd)
const result2 = array2.some(isOdd)

console.log(result1) // 1, 3, 5の奇数要素を含む配列なのでtrueを返す 
console.log(result2) // 配列の要素は偶数のみの為falseを返す

every

everyは配列の全ての要素が指定した条件を満たしているかを確認する際に使用します。

const array1 = [1, 2, 3, 4, 5, 6]
const array2 = [1, 3, 5]
function isOdd (num) {
  return num % 2 !==0;
}
// 配列の要素が全て奇数かどうかの判定
const result1 = array1.every(isOdd)
const result2 = array2.every(isOdd)

console.log(result1) // 配列内に偶数も含まれているのでfalseが返される
console.log(result2) // 全て奇数なのでtrueが返される

includes

includesメソッドを使用することで指定した要素が配列に含まれているかを知る事が出来ます。

includesメソッドは真偽値を返します。

const array = ['JavaScript', 'jQuery', 'React', 'Vue'];
const result1 = array.includes('React')
const result2 = array.includes('react')
console.log(result1) // true
console.log(result2) // false

Array.prototype.includes()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes