Ccmmutty logo
Commutty IT
0 pv6 min read

[JS] forEachより簡単なArray関数

https://cdn.magicode.io/media/notebox/04818d08-a0e0-4477-9233-22886ae3f329.jpeg

概要

配列の処理をする時、forEachを使う場合と他のArray関数を使う場合の比較をまとめました🎃

forEach以外のArray関数

map: 各要素に処理を適用して返す

例: 時間を分に変換して取得
元データ
const hours = [1, 24, 720];
forEachの場合
const minutes = [];
hours.forEach(h => minutes.push(h * 60));
mapの場合
const minutes = hours.map(h => h * 60);
minutesの出力結果
[ 60, 1440, 43200 ]
mapは新しい配列を返すので、pushする必要がなく、forEachより少しシンプルに書けます。

filter: 条件に一致する要素を返す

例: 12歳以下または60歳以上のユーザーを取得
元データ
const users = [
    {name: "Godric", age: 12},
    {name: "Helga", age: 13},
    {name: "Rowena", age: 59},
    {name: "Salazar", age: 60}
];
forEachの場合
const result = [];
users.forEach(user => {
    if (user.age <= 12 || user.age >= 60) result.push(user);
});
filterの場合
const result = users
    .filter(user => user.age <= 12 || user.age >= 60);
resultの出力結果
[ { name: 'Godric', age: 12 }, { name: 'Salazar', age: 60 } ]
※検索結果がヒットしなかった場合、空配列が返される。
filtermapと同様新しい配列を返し、if文やpushを書く必要がないので、forEachよりシンプルに書けます。

また、mapと組み合わせて必要な要素だけを取り出すこともできます。
const result = users
    .filter(user => user.age <= 12 || user.age >= 60)
    .map(user => user.name);
resultの出力結果
[ 'Godric', 'Salazar' ]

find: 条件に一致する最初の要素を返す

例: aで始まる最初の文字列を取得
元データ
const words = ['banana', 'apple', 'apricot', 'orange'];
forEachの場合
let result = undefined;
words.forEach(word=> {
    if (result === undefined && word.substring(0, 1) === 'a') {
        result = word;
    }
});
findの場合
const result = words.find(word => word.substring(0, 1) === 'a');
resultの出力結果
apple
※検索結果がヒットしなかった場合、undefinedが返される。
JavaScriptのforEachはループではなくArray関数の一種なので、breakができません。そのため、途中で処理を抜けるには条件を工夫する必要があります。
findを使ったほうが簡単です。

reduce: 全要素を集約して返す

例: 平均点、最高点、最低点をそれぞれ算出して取得
元データ
const scores = [82, 96, 70, 91, 88];
forEachの場合
let sum = 0;
let max = scores[0];
let min = scores[0];
scores.forEach(score => {
    sum += score;
    if (score > max) max = score;
    if (score < min) min = score;
});
const avg = sum / scores.length;
reduceの場合
const avg = scores.reduce((acc, curt) => acc + curt) / scores.length;
const max = scores.reduce((acc, curt) => acc > curt ? acc : curt);
const min = scores.reduce((acc, curt) => acc < curt ? acc : curt);
avg, max, minの出力結果
85.4
96
70
圧倒的にreduceのほうが簡単です。

some: 要素のうち最低1つが条件に一致するかチェックする

例: 90点以上のスコアがあるかチェック
元データ
const scores = [82, 96, 70, 91, 88];
forEachの場合
let result = false;
scores.forEach(score => {
    if (score >= 90) result = true;
});
someの場合
const result = scores.some(score => score >= 90);
resultの出力結果
true
forEachはbreakができないため、someのほうが良いです。

every: 全ての要素が条件に一致するかチェックする

例: 全てのスコアが90点以上かチェック
元データ
const scores = [82, 96, 70, 91, 88];
forEachの場合
let result = true;
scores.forEach(score => {
    if (score < 90) result = false;
});
everyの場合
const result = scores.every(score => score >= 90);
resultの出力結果
false
everysomeとまったく同じ条件で書けるので、こちらのほうが簡単です。

まとめ

  • map: 配列の要素を変換して取得する
  • filter / find: 条件に一致する配列の要素を取得する
  • reduce: 配列全体を集約して取得する
  • some / every: 配列の一部または全部で条件に一致する要素があるかチェックする
基本的にforEachを使うよりも上記の関数を使った方が、見た目もシンプルで簡単に書くことができます。
Thank you for reading🎃

Discussion

コメントにはログインが必要です。