JavaScriptの配列は、アプリケーション開発において最も頻繁に使用されるデータ構造の一つです。
この記事では、配列の基本的な操作から高度なテクニックまで、実践的な例を交えて解説します。
この記事でわかる事
以下の内容を習得することができます:
- 配列の考え方
- 配列の基本的な操作(作成、追加、削除、アクセス)
- 配列を使った効率的なデータ処理方法
- 多次元配列と連想配列の扱い方
- モダンなJavaScriptにおける配列の活用方法
- パフォーマンスを考慮した実装テクニック
1. 配列の基本
配列の考え方
配列とは「整理された箱」のようなものです
例えば、
文房具を机の上にバラバラに置いておくのと、筆箱に整理して入れておくのとでは、使い勝手が全然違いますよね。
配列は、このような「筆箱」のような役割を果たします。
具体的な例で見てみましょう:
// 文房具箱(配列)の例
const stationery = ["鉛筆", "消しゴム", "定規", "ボールペン"];
”[]”の中に複数の情報を格納し変数に代入できます。
この配列の特徴は:
最初(0番目)は “鉛筆”
次(1番目)は “消しゴム” というように、
それぞれの場所が決まっています
番号で管理されている
console.log(stationery[0]); // "鉛筆"を取り出す
console.log(stationery[1]); // "消しゴム"を取り出す
引き出しに番号がついているような感じです(マンションで言うルームナンバー
みたいなものです。)
注意したいのは、最初は0から始まります(これは少し慣れが必要かもしれません)
実践的な例:
javascriptCopy// クラスの出席番号と名前の管理
const studentNames = ["田中", "鈴木", "佐藤", "山田"];
// テストの点数管理
const testScores = [85, 92, 78, 95];
// 週間の予定管理
const weeklySchedule = ["買い物", "映画", "掃除", "勉強", "運動", "料理", "休憩"];
重要なポイント:
- 配列のインデックス(要素の位置)は0から始まります
- 配列には異なる型の値を混ぜて入れることができます
const
で宣言しても、配列の中身は変更できます(ただし配列自体を別の配列に置き換えることはできません)- 存在しないインデックスにアクセスすると
undefined
が返されます
これらの基本を理解すれば、配列を使った様々なデータ処理ができるようになります。
なぜ配列が必要なのか?配列の重要性
プログラミングにおいて、複数のデータを効率的に管理することは非常に重要です。
配列を使用することで、以下のような利点が得られます
- データの一括管理
- 関連するデータをまとめて扱える
- コードの可読性(読みやすさ)が向上する
- データの追加・削除・更新が容易
- 効率的なデータ処理
- ループ(繰り返し)処理による一括操作が可能
- 要素の検索や並び替えが簡単
- メモリの効率的な使用
- データ構造の表現
- リスト、スタック、キューなどの基本的なデータ構造を実現
- 複雑なデータ構造の基礎として活用
配列の宣言と初期化
// 空配列の宣言
const arr1 = []; // 角括弧を使う方法(一般的な方法)
const arr2 = new Array(); // Arrayクラスを使う方法(前者と同じ結果になります)
// 初期値がある配列
const numbers = [1, 2, 3, 4, 5]; // 数値だけの配列
// 色々な型を混ぜた配列も作れます
const mixed = [1, "hello", { name: "John" }, true];
// ↑ 数値、文字列、オブジェクト、真偽値が入っています
// サイズを指定して同じ値で初期化
const zeros = new Array(5).fill(0); // [0, 0, 0, 0, 0]
// ↑ 5つの要素を持つ配列を作り、すべてを0で埋めています
// 1から始まる連番を作成
const sequence = Array.from({length: 5}, (_, i) => i + 1); // [1, 2, 3, 4, 5]
// ↑ Array.fromで5要素の配列を作り、インデックスに1を足して1から始まる連番を作っています
配列の長さと要素数
const arr = [1, 2, 3];
console.log(arr.length); // 3
// lengthプロパティで配列の要素数を取得できます
要素へのアクセスと変更
const fruits = ["りんご", "バナナ", "オレンジ"];
console.log(fruits[0]); // "りんご"
// ↑ 配列の要素は0から始まる番号(インデックス)でアクセスします
console.log(fruits.at(-1)); // "オレンジ"
// ↑ at()メソッドを使うと、末尾から要素を取得できます
// -1は最後の要素、-2は後ろから2番目を意味します
// 要素の変更
fruits[1] = "ぶどう"; // インデックスを指定して値を変更できます
// この結果、配列は ["りんご", "ぶどう", "オレンジ"] となります
その他の配列構造
多次元配列
// 2次元配列の宣言と初期化
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// ↑ 配列の中に配列を入れることで、表やマトリックスのような構造を表現
// アクセス
console.log(matrix[0][1]); // 2
// ↑ matrix[行番号][列番号]でアクセス
連想配列(オブジェクト)
// JavaScriptには真の連想配列はなく、オブジェクトを使用
const obj = {
name: "John", // プロパティ名: 値
age: 30
};
// 要素の追加
obj.email = "john@example.com";
// ↑ ドット記法でプロパティを追加
2. 配列の操作
要素の追加
const arr = ["A", "B"];
// 末尾に追加 - push()メソッド
arr.push("C"); // ["A", "B", "C"]
// ↑ 配列の最後に新しい要素を追加します
// 先頭に追加 - unshift()メソッド
arr.unshift("Z"); // ["Z", "A", "B", "C"]
// ↑ 配列の先頭に新しい要素を追加します。既存の要素は後ろにずれます
// 途中に追加 - splice()メソッド
arr.splice(2, 0, "X"); // ["Z", "A", "X", "B", "C"]
// ↑ splice(追加位置, 削除する要素数, 追加する要素)
// この場合、インデックス2の位置に、何も削除せずに"X"を追加
要素の削除
const arr = ["A", "B", "C", "D"];
// 末尾から削除 - pop()メソッド
const last = arr.pop(); // arr: ["A", "B", "C"]
// ↑ 最後の要素を削除し、その要素を返します(last = "D")
// 先頭から削除 - shift()メソッド
const first = arr.shift(); // arr: ["B", "C"]
// ↑ 最初の要素を削除し、その要素を返します(first = "A")
// インデックス指定で削除 - splice()メソッド
arr.splice(1, 1); // arr: ["B"]
// ↑ インデックス1から1つの要素を削除します
要素の検索
const arr = ["A", "B", "C", "B"];
// インデックスを取得
console.log(arr.indexOf("B")); // 1
// ↑ 最初に見つかった"B"の位置(前から検索)
console.log(arr.lastIndexOf("B")); // 3
// ↑ 最後に見つかった"B"の位置(後ろから検索)
// 存在確認 - includes()メソッド
console.log(arr.includes("A")); // true
// ↑ 配列に指定した要素が含まれているかをチェック
配列の変換と処理
map, filter, reduce
const numbers = [1, 2, 3, 4, 5];
// 各要素を変換 - map()メソッド
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
// ↑ 各要素に対して同じ処理を行い、新しい配列を作成
// 条件で絞り込み - filter()メソッド
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
// ↑ 条件に合う要素だけを抽出して新しい配列を作成
// 集計 - reduce()メソッド
const sum = numbers.reduce((acc, cur) => acc + cur, 0); // 15
// ↑ 配列の要素を順番に処理して一つの値にまとめる
// acc: 累積値、cur: 現在の要素、0: 初期値
実践的なテクニック
重複の除去
const arr = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]
// ↑ Setオブジェクトを使って重複を除去し、スプレッド演算子(...)で配列に戻す
配列のシャッフル
const shuffle = arr => {
return arr.sort(() => Math.random() - 0.5);
};
// ↑ sort()とMath.random()を組み合わせてランダムに並び替え
この0.5
の役割について詳しく説明しましょう。
Math.random()
は0以上1未満の乱数を返します。
つまり:
Math.random()
の結果は 0 ≤ x < 1 の範囲の値になります
そこから0.5を引くことで:
- 結果は -0.5 ≤ x < 0.5 の範囲になります
この値がsort()
メソッドのコールバック関数として使われる際:
- 負の数が返された場合:最初の要素を前に配置
- 正の数が返された場合:最初の要素を後ろに配置
- 0が返された場合:順序は変更されない
つまり、Math.random() - 0.5
とすることで:
- 約50%の確率で負の数(-0.5~0)
- 約50%の確率で正の数(0~0.5)
が返されることになり、各要素の位置が約50%の確率で前後に移動することになります。これによってランダムなシャッフルが実現されます。
文字列と配列の変換
const str = "a,b,c";
const arr = str.split(","); // ["a", "b", "c"]
// ↑ カンマで区切られた文字列を配列に変換
const joined = arr.join(","); // "a,b,c"
// ↑ 配列の要素をカンマで結合して文字列に変換
3.具体的な実用例
1. ユーザー管理システム
// ユーザー情報を配列で管理
// 各ユーザーはオブジェクト(id, name, roleのプロパティを持つ)として表現
const users = [
{ id: 1, name: "田中", role: "admin" },
{ id: 2, name: "鈴木", role: "user" },
{ id: 3, name: "佐藤", role: "user" }
];
// filter()メソッドを使って管理者(role: "admin")のみを抽出
// filterは条件に合う要素だけを集めた新しい配列を作ります
const admins = users.filter(user => user.role === "admin");
// 結果: [{ id: 1, name: "田中", role: "admin" }]
// map()メソッドを使ってユーザー名の一覧を作成
// mapは各要素を変換した新しい配列を作ります
const userNames = users.map(user => user.name);
// 結果: ["田中", "鈴木", "佐藤"]
このコードのポイント:
- オブジェクトの配列を使うことで、関連する情報(id、名前、役割)をまとめて管理できます
filter()
は条件に合う要素だけを取り出すのに便利ですmap()
は配列の各要素から必要な情報だけを取り出すのに使います
2. ショッピングカート
// カート内の商品を配列で管理
// 各商品は商品ID、名前、価格、数量の情報を持つ
const cart = [
{ id: "item1", name: "Tシャツ", price: 2000, quantity: 2 },
{ id: "item2", name: "ジーンズ", price: 5000, quantity: 1 }
];
// reduce()メソッドを使って合計金額を計算
// reduceは配列の要素を1つずつ処理して、単一の値にまとめます
const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
// 計算過程:
// 1周目: 0 + (2000 × 2) = 4000
// 2周目: 4000 + (5000 × 1) = 9000
// 結果: 9000
// 配列のlengthプロパティで品目数を取得
const itemCount = cart.length; // 結果: 2
このコードのポイント:
- 各商品の情報をオブジェクトとして持つことで、商品ごとの詳細情報を管理できます
reduce()
は配列の要素を集計するのに適していますlength
プロパティで配列の要素数を簡単に取得できます
3. TODOリスト
// TODOタスクを配列で管理
// 各タスクはID、タスク内容、完了状態の情報を持つ
const todos = [
{ id: 1, task: "買い物", completed: false },
{ id: 2, task: "勉強", completed: true }
];
// filter()を使って未完了のタスクだけを抽出
// completedがfalseのタスクだけを集めます
const incompleteTasks = todos.filter(todo => !todo.completed);
// 結果: [{ id: 1, task: "買い物", completed: false }]
// push()メソッドで新しいタスクを追加
// 配列の末尾に新しい要素を追加します
todos.push({ id: 3, task: "運動", completed: false });
// 結果: todos配列に新しいタスクが追加される
このコードのポイント:
- 各タスクの状態(完了/未完了)を管理できます
filter()
で簡単に未完了タスクを抽出できますpush()
で簡単に新しいタスクを追加できます
4. データ分析
// 日々の売上データを配列で管理
// 単純な数値の配列として表現
const sales = [120, 200, 350, 100, 280];
// reduce()を使って合計を計算し、lengthで割って平均を算出
const average = sales.reduce((sum, sale) => sum + sale) / sales.length;
// 計算過程:
// 1. reduce()で合計を計算: 120 + 200 + 350 + 100 + 280 = 1050
// 2. 配列の長さ(5)で割る: 1050 / 5 = 210
// 結果: 210
// filter()を使って売上目標(200)以上の日を抽出
const goodSalesDays = sales.filter(sale => sale >= 200);
// 結果: [200, 350, 280]
このコードのポイント:
- 数値の配列でデータを管理し、様々な計算や分析が可能です
reduce()
とlength
を組み合わせて平均値を計算できますfilter()
で条件に合うデータを簡単に抽出できます
5.データの変換
// CSVのような文字列データを配列に変換
const csvData = "りんご,バナナ,オレンジ";
// split()メソッドで文字列をカンマで区切って配列に変換
const fruits = csvData.split(",");
// 結果: ["りんご", "バナナ", "オレンジ"]
// 配列を文字列に戻す
// join()メソッドで配列の要素を指定した区切り文字でつなげる
const backToString = fruits.join("-");
// 結果: "りんご-バナナ-オレンジ"
このコードのポイント:
split()
で文字列を配列に変換できますjoin()
で配列を文字列に戻せます- 区切り文字は自由に指定可能です
4.まとめ
この記事では、JavaScriptにおける配列の扱い方を総合的に解説してきました。
基本的な操作から高度なテクニックまで、実践的な例を交えて説明しました。
配列は単なるデータの集まり以上の存在で、適切に使用することで効率的なデータ処理が可能になります。
特に重要なポイントは以下の通りです:
- 配列の基本操作(push/pop, unshift/shift)を使いこなすことで、データの追加・削除を効率的に行えます
- map/filter/reduceなどの高階関数を活用することで、データの変換や集計を簡潔に記述できます
- スプレッド構文や分割代入などのモダンな機能を活用することで、より読みやすいコードを書くことができます
- 多次元配列や連想配列(オブジェクト)を適切に使い分けることで、複雑なデータ構造も表現できます
- パフォーマンスを意識した実装を行うことで、大規模なデータ処理も効率的に行えます
これらの知識を組み合わせることで、より効率的で保守性の高いJavaScriptプログラミングが可能になります。
配列は非常に柔軟なデータ構造であり、その特性を理解して適切に活用することが、効果的なプログラミングの鍵となります。
次のステップとして、これらの基礎的な知識を活かして、実際のプロジェクトでの応用方法を探ってみることをお勧めします。