
JavaScriptの配列操作(map, filter, forEachなど)
2025-07-28配列操作の基本
JavaScriptの配列は、データの集合を効率的に操作するための強力なメソッドを多数提供しています。ES5(ECMAScript 5)で導入された配列メソッドは、関数型プログラミングスタイルを可能にし、コードをより宣言的に書くことができます。
主要な配列メソッド
1. forEach – 各要素に対する処理
forEach
は配列の全要素に順番にアクセスし、指定した関数を実行します。戻り値はなく、配列を変更しません。主に繰り返し処理や画面表示、ログ出力などに使います。break
やreturn
で途中終了はできません。
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 – 配列の変換
map
は配列の各要素に関数を適用し、その結果を新しい配列として返します。元の配列は変更されません。例えば数値配列の各要素を2倍にしたり、オブジェクト配列から特定のプロパティだけを取り出すときに使います。
const doubled = numbers.map(number => number * 2);
console.log(doubled); // [2, 4, 6]
特徴:
- 新しい配列を返す
- 元の配列は変更されない
- 各要素を1対1で変換
3. filter – 条件に合う要素の抽出
filter
は配列から条件を満たす要素だけを抜き出し、新しい配列として返します。元の配列は変更されません。例えば偶数だけを抽出する、特定の文字列を含む要素だけを取得するなどに便利です。
const evens = numbers.filter(number => number % 2 === 0);
console.log(evens); // [2]
特徴:
- 新しい配列を返す
- コールバック関数が
true
を返した要素のみ含まれる - 元の配列は変更されない
4. reduce – 配列の畳み込み
reduce
は配列の全要素を順に処理し、1つの値にまとめます。合計値、平均値、オブジェクトの集計などに使われます。初期値を設定でき、要素ごとに計算結果を次の要素処理に引き継ぐことができます。
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 6
特徴:
- 配列を単一の値に集約
- 初期値を指定可能(省略すると最初の要素が初期値になる)
- 多彩な用途(集計、変換、フラット化など)
5. find / findIndex – 要素の検索
find
は条件に合う最初の要素を返し、findIndex
はそのインデックス(位置)を返します。条件に合うものがない場合、find
はundefined
、findIndex
は-1
を返します。
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 – 条件チェック
some
は配列の中で1つでも条件を満たせばtrue
を返します。every
は全ての要素が条件を満たすときのみtrue
を返します。部分一致か全一致かで使い分けます。
const hasEven = numbers.some(n => n % 2 === 0); // true
const allEven = numbers.every(n => n % 2 === 0); // false
7. sort – 配列のソート
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
は条件を満たせば途中で終了
まとめ
JavaScriptの代表的な配列メソッドを学ぶことで、コードを短く効率的に書けるようになります。forEachやmapなどを使えば、従来のfor文より読みやすく、意図が明確な処理が可能です。filterやfindで条件抽出、reduceで集計や加工、sortで並び替えなど、実用的な操作が簡単に行えます。これらを活用することで、保守性や再利用性が高まり、開発スピードも向上します。
演習問題
初級問題(3問)
- 次の配列の各要素を2倍した新しい配列を作成しなさい(mapを使用)。
const numbers = [1, 2, 3, 4, 5];
- 次の配列から文字列の要素だけを抽出しなさい(filterを使用)。
const mixed = [1, 'apple', 2, 'banana', true, 'orange'];
- 次のコードの出力結果は?
const arr = [10, 20, 30];
arr.forEach(num => {
num = num * 2;
});
console.log(arr);
中級問題(6問)
- 次の配列から偶数のみを抽出し、それぞれを3倍して、結果の合計を求めなさい。
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- 次のオブジェクトの配列から、ageが30以上の人のnameだけを含む配列を作成しなさい。
const people = [
{ name: '太郎', age: 25 },
{ name: '花子', age: 30 },
{ name: '次郎', age: 35 }
];
- 次の2つの配列を結合し、重複を除去した新しい配列を作成しなさい。
const arr1 = [1, 2, 3];
const arr2 = [2, 3, 4, 5];
- 次の配列を文字列の長さでソートしなさい。
const fruits = ['apple', 'banana', 'cherry', 'date'];
- 次の配列の要素の平均値を求めなさい(reduceを使用)。
const scores = [85, 90, 78, 92, 88];
- 次のコードの出力結果とその理由を説明しなさい。
const arr = [1, 2, 3];
const result = arr.map((num, index) => num * index);
console.log(result);
上級問題(3問)
- 次のような動作をする
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 }
]
} */
- 配列のフラット化処理を行う
flatten
関数を再帰的に実装しなさい(任意の深さに対応)。
const nested = [
1, [
2, [
3, [
4
]
],
5]
];
const flat = flatten(nested); console.log(flat); // [1, 2, 3, 4, 5]
- 次のような動作をする
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]]
解答例
初級問題解答
- mapを使用
const doubled = numbers.map(n => n * 2);
- filterを使用
const strings = mixed.filter(item => typeof item === 'string');
- 出力結果
[10, 20, 30]
const arr = [10, 20, 30];
arr.forEach(num => {
num = num * 2;
});
console.log(arr); // [10, 20, 30]と表示される。
// forEach内のnumは新しい変数であり、元の配列arrには影響しない。
中級問題解答
- チェーンして処理
const result = numbers
.filter(n => n % 2 === 0)
.map(n => n * 3)
.reduce((sum, n) => sum + n, 0);
- フィルタリングとマッピング
const names = people
.filter(person => person.age >= 30)
.map(person => person.name);
- 結合と重複除去
const arr1 = [1, 2, 3];
const arr2 = [2, 3, 4, 5];
const combined = [...new Set([...arr1, ...arr2])];
- 文字列長でソート
const fruits = ['apple', 'banana', 'cherry', 'date'];
fruits.sort((a, b) => a.length - b.length);
- 平均値の計算
const scores = [85, 90, 78, 92, 88];
const average = scores.reduce((sum, score) => sum + score, 0) / scores.length;
- 出力結果と理由:
[0, 2, 6]
const arr = [1, 2, 3];
const result = arr.map((num, index) => num * index);
console.log(result); // [0, 2, 6]が出力されます。
// mapメソッドは配列の各要素に対して関数を適用し、新しい配列を生成します。
上級問題解答
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;
}, {});
}
flatten
関数
function flatten(arr) {
return arr.reduce((flat, toFlatten) => {
return flat.concat( Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten );
}, []);
}
chunk
関数
javascript function chunk(array, size) {
return array.reduce((acc, _, i) => { if (i % size === 0) { acc.push(array.slice(i, i + size)); }
return acc; }, []);
}