JavaScriptの配列操作(map, filter, forEachなど)

2025-07-28

配列操作の基本

JavaScriptの配列は、データの集合を効率的に操作するための強力なメソッドを多数提供しています。ES5(ECMAScript 5)で導入された配列メソッドは、関数型プログラミングスタイルを可能にし、コードをより宣言的に書くことができます。

主要な配列メソッド

1. forEach – 各要素に対する処理

const numbers = [1, 2, 3];

// 従来のforループ
for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

// forEachを使用
numbers.forEach(number => {
  console.log(number);
});

特徴

  • 戻り値はundefined
  • ループを途中で止められない(breakが使えない)
  • 配列の要素を変更可能(元の配列を変更する)

2. map – 配列の変換

const doubled = numbers.map(number => number * 2);
console.log(doubled); // [2, 4, 6]

特徴

  • 新しい配列を返す
  • 元の配列は変更されない
  • 各要素を1対1で変換

3. filter – 条件に合う要素の抽出

const evens = numbers.filter(number => number % 2 === 0);
console.log(evens); // [2]

特徴

  • 新しい配列を返す
  • コールバック関数がtrueを返した要素のみ含まれる
  • 元の配列は変更されない

4. reduce – 配列の畳み込み

const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 6

特徴

  • 配列を単一の値に集約
  • 初期値を指定可能(省略すると最初の要素が初期値になる)
  • 多彩な用途(集計、変換、フラット化など)

5. find / findIndex – 要素の検索

const users = [
  { id: 1, name: '太郎' },
  { id: 2, name: '花子' }
];

const user = users.find(user => user.id === 2);
console.log(user); // { id: 2, name: '花子' }

const index = users.findIndex(user => user.name === '太郎');
console.log(index); // 0

6. some / every – 条件チェック

const hasEven = numbers.some(n => n % 2 === 0); // true
const allEven = numbers.every(n => n % 2 === 0); // false

7. sort – 配列のソート

const unsorted = [3, 1, 4, 2];
const sorted = unsorted.sort((a, b) => a - b); // [1, 2, 3, 4]

注意点

  • 元の配列を変更する
  • デフォルトは文字列としてのソート(数値ソートには比較関数が必要)

メソッドチェーン

配列メソッドはチェーンして使用できます。メソッドチェーン(method chaining)とは、複数のメソッドを「ドット(.)」でつなげて連続して呼び出す書き方です。処理を一行でスッキリ書けるのが特徴です。

const result = numbers
  .filter(n => n % 2 === 0) // 偶数だけ抽出
  .map(n => n * 3) // 3倍する
  .reduce((sum, n) => sum + n, 0); // 合計を計算

console.log(result); // 6 (2 * 3 = 6)

ES6+の新しい配列機能

スプレッド演算子

配列やオブジェクトの中身を展開する記号。

const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

Array.from()

配列のようなもの(Array-like)やイテラブル(例:文字列、Set)を、本物の配列に変換するメソッド。

const arrayLike = { 0: 'a', 1: 'b', length: 2 };
const realArray = Array.from(arrayLike); // ['a', 'b']

分割代入

配列やオブジェクトの中の値を、変数にまとめて取り出す書き方。

const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]

パフォーマンスの考慮

  • 大きな配列forループの方が高速な場合あり
  • 不変性map/filter/sliceは新しい配列を作成(メモリ使用量に注意)
  • 早期終了some/everyは条件を満たせば途中で終了

演習問題

初級問題(3問)

  1. 次の配列の各要素を2倍した新しい配列を作成しなさい(mapを使用)。
   const numbers = [1, 2, 3, 4, 5];
  1. 次の配列から文字列の要素だけを抽出しなさい(filterを使用)。
   const mixed = [1, 'apple', 2, 'banana', true, 'orange'];
  1. 次のコードの出力結果は?
   const arr = [10, 20, 30];
   arr.forEach(num => {
     num = num * 2;
   });
   console.log(arr);

中級問題(6問)

  1. 次の配列から偶数のみを抽出し、それぞれを3倍して、結果の合計を求めなさい。
   const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  1. 次のオブジェクトの配列から、ageが30以上の人のnameだけを含む配列を作成しなさい。
   const people = [
     { name: '太郎', age: 25 },
     { name: '花子', age: 30 },
     { name: '次郎', age: 35 }
   ];
  1. 次の2つの配列を結合し、重複を除去した新しい配列を作成しなさい。
   const arr1 = [1, 2, 3];
   const arr2 = [2, 3, 4, 5];
  1. 次の配列を文字列の長さでソートしなさい。
   const fruits = ['apple', 'banana', 'cherry', 'date'];
  1. 次の配列の要素の平均値を求めなさい(reduceを使用)。
   const scores = [85, 90, 78, 92, 88];
  1. 次のコードの出力結果とその理由を説明しなさい。
   const arr = [1, 2, 3];
   const result = arr.map((num, index) => num * index);
   console.log(result);

上級問題(3問)

  1. 次のような動作をするgroupBy関数を実装しなさい。
const people = [ 
    { name: '太郎', age: 25 }, 
    { name: '花子', age: 30 }, 
    { name: '次郎', age: 25 } 
]; 
const grouped = groupBy(people, 'age'); /* 
結果: { '25':
         [ 
             { name: '太郎', age: 25 },
             { name: '次郎', age: 25 } 
         ],
       '30': [
             { name: '花子', age: 30 }
             ]
     } */
  1. 配列のフラット化処理を行うflatten関数を再帰的に実装しなさい(任意の深さに対応)。
const nested = [
    1, [
        2, [
            3, [
                4
               ]
            ],
        5]
    ]; 
const flat = flatten(nested); console.log(flat); // [1, 2, 3, 4, 5]
  1. 次のような動作をするchunk関数を実装しなさい。
javascript const array = [1, 2, 3, 4, 5, 6, 7]; 
const chunked = chunk(array, 3); console.log(chunked); // [[1, 2, 3], [4, 5, 6], [7]]

解答例

初級問題解答

  1. mapを使用
   const doubled = numbers.map(n => n * 2);
  1. filterを使用
   const strings = mixed.filter(item => typeof item === 'string');
  1. 出力結果
[10, 20, 30]
    const arr = [10, 20, 30];
    arr.forEach(num => {
        num = num * 2;
    });
    console.log(arr);   // [10, 20, 30]と表示される。
                        // forEach内のnumは新しい変数であり、元の配列arrには影響しない。

中級問題解答

  1. チェーンして処理
   const result = numbers
     .filter(n => n % 2 === 0)
     .map(n => n * 3)
     .reduce((sum, n) => sum + n, 0);
  1. フィルタリングとマッピング
   const names = people
     .filter(person => person.age >= 30)
     .map(person => person.name);
  1. 結合と重複除去
   const arr1 = [1, 2, 3];
   const arr2 = [2, 3, 4, 5];
   const combined = [...new Set([...arr1, ...arr2])];
  1. 文字列長でソート
   const fruits = ['apple', 'banana', 'cherry', 'date'];
   fruits.sort((a, b) => a.length - b.length);
  1. 平均値の計算
   const scores = [85, 90, 78, 92, 88];
   const average = scores.reduce((sum, score) => sum + score, 0) / scores.length;
  1. 出力結果と理由:
   [0, 2, 6]
    const arr = [1, 2, 3];
    const result = arr.map((num, index) => num * index);
    console.log(result);    // [0, 2, 6]が出力されます。
                            // mapメソッドは配列の各要素に対して関数を適用し、新しい配列を生成します。

上級問題解答

  1. groupBy関数
function groupBy(array, key) { 
    return array.reduce((acc, obj) => { 
        const groupKey = obj[key]; 
        if (!acc[groupKey]) { acc[groupKey] = []; } 
        acc[groupKey].push(obj); 
        return acc; 
    }, {}); 
}
  1. flatten関数
function flatten(arr) { 
    return arr.reduce((flat, toFlatten) => { 
        return flat.concat( Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten ); 
    }, []); 
}
  1. chunk関数
javascript function chunk(array, size) { 
    return array.reduce((acc, _, i) => { if (i % size === 0) { acc.push(array.slice(i, i + size)); } 
    return acc; }, []); 
}