JavaScriptの配列の応用テクニック!よく使う便利な書き方まとめ
生徒
「先生、JavaScriptの配列って基本はわかるけど、もっと便利で使いやすいテクニックってありますか?」
先生
「ありますよ。配列はデータを整理する強力な道具なので、応用テクニックを覚えるとずっと効率よく扱えます。具体的な便利な書き方をいくつか紹介しましょう!」
生徒
「ぜひ教えてください!」
1. スプレッド構文で配列を簡単にコピー・結合する
JavaScriptで配列を扱う際、もっとも頻繁に使う便利なテクニックの一つが「スプレッド構文(...)」です。ドットを3つ書くだけで、配列の「中身だけ」をバラバラに取り出して展開することができます。
プログラミング未経験の方でも直感的に理解できるよう、まずは2つの配列を1つにまとめる(結合する)例を見てみましょう。例えば、前半の数字と後半の数字を合体させて新しいリストを作るイメージです。
let firstGroup = [10, 20];
let secondGroup = [30, 40];
// スプレッド構文で2つを合体!
let allNumbers = [...firstGroup, ...secondGroup];
console.log(allNumbers);
[10, 20, 30, 40]
このように、[...配列名]と書くことで、元の配列を壊さずに新しい配列へ中身を詰め替えることができます。また、配列を丸ごとコピーしたいときにも非常に役立ちます。通常の代入(copy = original)では、片方を変えるともう片方も変わってしまう「参照」の問題が起きますが、スプレッド構文を使えば、完全に別の「複製」として扱えるため、予期せぬバグを防ぐことができます。
let original = ["りんご", "みかん"];
// 中身をコピーして新しい配列を作成
let copyList = [...original];
// コピーしたものに新しく追加しても、元のは変わらない
copyList.push("バナナ");
console.log("元のリスト:", original);
console.log("コピーしたリスト:", copyList);
元のリスト: ["りんご", "みかん"]
コピーしたリスト: ["りんご", "みかん", "バナナ"]
この書き方は、モダンなJavaScript開発において「不変性(イミュータビリティ)」を保つために必須の知識です。シンプルでミスが少なく、コードの可読性(読みやすさ)も格段に上がるため、真っ先にマスターしておきましょう。
2. map()で配列の中身を変換する
JavaScriptの配列操作において、実務で最も頻繁に登場するのがこの「map()」です。一言でいうと、「元の配列の要素を一つずつ取り出し、特定の加工をしてから新しい配列を作る」という機能を持っています。
最大の特徴は、元の配列(オリジナル)を書き換えないこと。これは「イミュータビリティ(不変性)」と呼ばれ、思わぬデータの上書きミスを防ぐために非常に重要な考え方です。プログラミング未経験の方でも、工場のベルトコンベアをイメージすると分かりやすいでしょう。流れてくる部品(データ)に一つずつスタンプを押して、完成品を別の箱に並べていくような仕組みです。
それでは、数字のリストをすべて2倍に書き換えるシンプルな例を見てみましょう。
let numbers = [1, 2, 3];
// mapを使って「各要素を2倍にする」という処理を適用
let doubled = numbers.map(num => {
return num * 2;
});
console.log("元の配列:", numbers);
console.log("変換後の配列:", doubled);
元の配列: [1, 2, 3]
変換後の配列: [2, 4, 6]
さらに実用的な例として、商品の「名前」と「価格」が入ったリストから、価格だけを抜き出して「円」という文字を付け加えるような使い方もできます。
let prices = [100, 200, 300];
// 数字の後に「円」をつけて文字列に変換する
let labelList = prices.map(price => price + "円");
console.log(labelList);
["100円", "200円", "300円"]
このように、数値計算だけでなく「データの見た目を整える」ときにもmap()は抜群の威力を発揮します。一つひとつの要素に対して繰り返し処理を手動で書く(for文など)必要がないため、コードがスッキリして読みやすくなるのがメリットです。
3. filter()で条件に合う要素だけ取り出す
実務のWeb開発で「特定のデータだけを抽出したい」という場面は非常に多いです。そんな時に活躍するのがfilter()メソッドです。名前の通り、フィルター(ろ過器)を通すように、配列の中から特定の条件に一致するデータだけを抜き出して、新しい配列を作成します。
まずは直感的に理解するために、数字のリストから「偶数だけ」を拾い上げるサンプルを見てみましょう。条件式が「true(正しい)」になった要素だけが、新しい箱(配列)に残る仕組みです。
let numbers = [1, 2, 3, 4, 5, 6];
// filterを使って「2で割り切れる数(偶数)」だけを抽出
let evens = numbers.filter(num => {
return num % 2 === 0;
});
console.log("元の配列:", numbers);
console.log("抽出後の配列:", evens);
元の配列: [1, 2, 3, 4, 5, 6]
抽出後の配列: [2, 4, 6]
プログラミング未経験の方にとっては、「不合格なものは取り除かれ、合格したものだけが残る」というイメージを持つと分かりやすいでしょう。例えば、ECサイトの検索機能で「5000円以下の商品だけを表示する」といった絞り込み処理も、このfilter()を使えば数行で実装できてしまいます。
もう一つ、より実戦に近い例として、ユーザーリストから「20歳以上の人」だけを絞り込むコードを紹介します。
let users = [
{ name: "佐藤", age: 18 },
{ name: "鈴木", age: 25 },
{ name: "高橋", age: 30 }
];
// 年齢が20以上の人だけをフィルタリング
let adults = users.filter(user => user.age >= 20);
console.log(adults);
[
{ "name": "鈴木", "age": 25 },
{ "name": "高橋", "age": 30 }
]
このように、複雑なデータ構造(オブジェクトの配列)であっても、条件を一つ書くだけでスマートに目的のデータを取り出すことができます。map()と同様、元の配列を変更しない(破壊しない)ため、安全でバグの起きにくいコードを書くための必須テクニックです。
4. find()で条件に合う最初の要素を取得する
大量のデータの中から「たった一つだけ」特定の条件に当てはまるものを探し出したいときに役立つのが、このfind()メソッドです。前述したfilter()は条件に合うものを「すべて」集めて新しいリストを作りますが、find()は「最初に見つかった一つ」を見つけ次第、そこで探索を終了して値を返してくれるのが大きな違いです。
イメージとしては、出席簿の中から特定の名前の人を一人だけ探し出すような動作です。もし条件に一致するものが複数あったとしても、返ってくるのは一番最初に見つかったデータだけになります。
まずは、ユーザーリストの中から「特定の名前を持つ人」を検索する例を見てみましょう。
let users = [
{ name: "太郎", age: 25 },
{ name: "花子", age: 30 },
{ name: "次郎", age: 25 }
];
// 「名前が花子さん」である最初のデータを探す
let targetUser = users.find(user => {
return user.name === "花子";
});
console.log("検索結果:", targetUser);
検索結果: { name: "花子", age: 30 }
このメソッドの便利な点は、ID(識別番号)などを使って特定の情報を一本釣りしたいときです。例えば、ECサイトで「商品IDが105番のデータだけを詳しく見たい」というような場面で非常によく使われます。
let products = [
{ id: 101, title: "ノートPC" },
{ id: 105, title: "マウス" },
{ id: 110, title: "キーボード" }
];
// IDが105の商品を検索
let selectedItem = products.find(item => item.id === 105);
console.log("選択された商品名:", selectedItem.title);
選択された商品名: マウス
注意点として、もし条件に合うものが一つも見つからなかった場合は、undefined(値がない状態)が返ってきます。そのため、「見つからなかったときの処理」もセットで考えるのがプロの書き方です。シンプルながらも、Webアプリの検索機能やログイン処理など、実務での登場回数が非常に多い重要なテクニックです。
5. reduce()で配列を一つの値に集約する
JavaScriptの配列操作の中で、もっともパワフルでありながら、少しコツが必要なのがこの「reduce()」です。名前の通り、配列にある複数の要素を「還元(reduce)」して、最終的にたった一つの値(合計点や平均値、あるいは一つのオブジェクトなど)にまとめ上げる機能を持っています。
初心者のうちは、「貯金箱」をイメージすると分かりやすいでしょう。空の貯金箱(初期値)に、配列の中身(コイン)を一つずつ順番に入れていき、最後に残った中身が合計金額になるという仕組みです。この「一歩ずつ計算を積み上げていく」感覚が、reduce()を使いこなす鍵となります。
まずは、数値の配列をすべて足し合わせて「合計」を出す、もっとも標準的な使い方を見てみましょう。
let scores = [10, 20, 30, 40];
// totalは「これまでの合計」、scoreは「今から足す要素」
let totalSum = scores.reduce((total, score) => {
return total + score;
}, 0); // この「0」が、最初の貯金箱の状態(初期値)です
console.log("合計スコア:", totalSum);
合計スコア: 100
このコードの裏側では、0 + 10、次に10 + 20、その次に30 + 30……といった具合に、前の計算結果が次のループへと引き継がれています。この「計算結果のリレー」ができる点が、他のメソッドにはないreduce()最大の特徴です。
応用例として、買い物リストの合計金額を計算するような実戦的なパターンも紹介します。単なる数字の列だけでなく、データのかたまり(オブジェクト)から特定の項目だけを抽出して集計することも可能です。
let cart = [
{ item: "消しゴム", price: 100 },
{ item: "ノート", price: 200 },
{ item: "ペン", price: 150 }
];
// 商品の価格だけを順番に足していく
let totalPrice = cart.reduce((sum, product) => {
return sum + product.price;
}, 0);
console.log("レジでの合計金額:", totalPrice + "円");
レジでの合計金額: 450円
reduce()をマスターすると、データの集計や加工が驚くほどスマートに書けるようになります。最初は難しく感じるかもしれませんが、「初期値を設定して、順番に積み上げていく」という基本ルールさえ押さえれば、配列操作の幅がぐっと広がります。
6. includes()で配列に特定の値があるかチェックする
プログラムを書いていると、「このリストの中に、特定のデータが入っているかな?」と確認したい場面がよくあります。そんな時に最もシンプルで便利なのが「includes()(インクルーズ)」メソッドです。このメソッドは、指定した値が配列に含まれていれば true(はい)、含まれていなければ false(いいえ) という二択の結果を返してくれます。
まずは、身近な買い物リストを例に、特定の果物がリストにあるかどうかをチェックするコードを見てみましょう。
let fruits = ["りんご", "みかん", "バナナ"];
// 「みかん」が含まれているかチェック
let hasMikan = fruits.includes("みかん");
console.log("みかんはある?:", hasMikan);
// 「ぶどう」が含まれているかチェック
let hasBudo = fruits.includes("ぶどう");
console.log("ぶどうはある?:", hasBudo);
みかんはある?: true
ぶどうはある?: false
以前のJavaScriptでは、値の位置(何番目か)を調べる複雑な書き方が一般的でしたが、現在は includes() を使うことで「あるかないか」を直感的に判断できるようになりました。プログラミング未経験の方でも、まるで英語の文章を読むように「fruits includes mikan?(フルーツにみかんは含まれる?)」と理解できるのがメリットです。
実務では、例えば「許可されたユーザーリストに名前があるか確認する」といった、セキュリティや権限チェックの条件分岐(if文)で非常によく使われます。シンプルながら、コードの読みやすさと安全性を高めてくれる強力なテクニックです。
7. 配列の空チェックはlengthで行う
配列が空かどうか調べるときは、配列の長さを表すlengthを使います。0なら空の配列です。
let arr = [];
if (arr.length === 0) {
console.log("配列は空です");
}
空の配列かどうかはプログラムの分岐でよく使うチェックポイントです。
8. 配列の並び替えはsort()を使う
sort()は配列の要素を並び替えます。ただし、文字列の場合は正しく並びますが、数値は注意が必要です。
数値を正しく並び替える例はこちら。
let numbers = [10, 5, 20, 1];
// 比較関数を渡すと正しく数値順に並ぶ
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 5, 10, 20]
比較関数なしだと、文字列として並ぶので注意しましょう。
9. 配列を文字列に変換するときはjoin()を使う
join()は配列の中身を指定した文字でつなげて一つの文字列にします。例えば、カンマやスペースでつなげることができます。
let arr = ["りんご", "みかん", "バナナ"];
console.log(arr.join(", ")); // りんご, みかん, バナナ
文字列として表示したいときに便利なメソッドです。
10. 配列のネストとフラット化(flat())
配列の中に配列が入っている場合を「ネストされた配列」と言います。そんな時はflat()を使うと一段階だけ中身を取り出してフラットな配列にできます。
let nested = [1, 2, [3, 4], 5];
let flat = nested.flat();
console.log(flat); // [1, 2, 3, 4, 5]
深いネストがある場合は引数に数字を入れて何段階かフラット化できます。
まとめ
ここまで、JavaScriptにおける配列操作の応用テクニックを幅広く解説してきました。配列はプログラミングにおいてデータの集合を扱う最も基本的な構造ですが、その操作方法は多岐にわたります。今回ご紹介した手法を使いこなすことで、コードの記述量を劇的に減らしつつ、読みやすくてメンテナンス性の高いプログラムを書くことができるようになります。
モダンな配列操作の重要性
近年のJavaScript開発(ES6以降)では、従来のfor文やwhile文を使った命令的なループ処理よりも、map、filter、reduceといった「宣言的」なメソッドを使うスタイルが主流となっています。これらを使うメリットは、**「何がしたいのか」がコードから一目で分かること**です。
例えば、特定の条件でデータを抽出したいときにfilterを使っていれば、他のエンジニア(あるいは未来の自分)がコードを見た際に「あ、ここではデータの絞り込みをしているんだな」と即座に理解できます。このような自己充足的なコード(Self-documenting code)を書くことは、チーム開発において非常に重要です。
各メソッドの使い分けガイド
今回学んだテクニックを整理すると、以下のような使い分けになります。
- 新しい配列を作りたいとき:
map(変換)、filter(抽出)、[...arr](コピー・結合) - 一つの値を導き出したいとき:
find(検索)、reduce(集計)、includes(存在確認) - 見た目や形式を整えたいとき:
sort(並び替え)、join(文字列化)、flat(平坦化)
実践的なサンプルプログラム
最後に、これらを組み合わせた少し実践的な例を見てみましょう。例えば、「商品リストから在庫があるものだけを選び、名前の配列を作って、カンマ区切りで表示する」という処理は、メソッドチェーンを使うと次のように美しく書けます。
const products = [
{ id: 1, name: "ノートPC", stock: 5 },
{ id: 2, name: "マウス", stock: 0 },
{ id: 3, name: "キーボード", stock: 12 },
{ id: 4, name: "モニター", stock: 8 }
];
// 在庫がある商品(stock > 0)を抽出し、名前だけの配列に変換して結合する
const availableProductNames = products
.filter(item => item.stock > 0)
.map(item => item.name)
.join("、");
console.log("購入可能な商品リスト: " + availableProductNames);
実行結果は以下の通りです。
購入可能な商品リスト: ノートPC、キーボード、モニター
このように、各メソッドを繋げて書く(メソッドチェーン)ことで、複雑なデータ加工もステップバイステップで論理的に記述できます。
さらなるステップアップ:TypeScriptでの活用
大規模な開発現場では、JavaScriptに型定義を追加した**TypeScript**が使われることが一般的です。配列操作においても、型を意識することでより安全なコーディングが可能になります。
interface User {
id: number;
name: string;
isActive: boolean;
}
const userList: User[] = [
{ id: 1, name: "田中", isActive: true },
{ id: 2, name: "佐藤", isActive: false }
];
// isActiveがtrueのユーザーを検索(見つからない可能性もあるのでundefinedを考慮)
const activeUser: User | undefined = userList.find(u => u.isActive);
if (activeUser) {
console.log(`${activeUser.name}さんはオンラインです。`);
}
JavaScriptの柔軟な配列操作をマスターすることは、プログラミングスキルの土台を固めることに直結します。まずは日々のコーディングの中で、意識的にこれらのメソッドを取り入れてみてください。最初は難しく感じるかもしれませんが、一度慣れてしまえば、もう昔の不便な書き方には戻れなくなるはずです。
生徒
「先生、ありがとうございました!配列の操作って、ただ要素を取り出すだけじゃなくて、こんなに色々なアプローチがあるんですね。特にスプレッド構文やメソッドチェーンは、コードがすごくスッキリして驚きました。」
先生
「そうでしょう。特にmapやfilterを使いこなせるようになると、JavaScriptの面白さが一段と増してきますよ。命令的に『どうやってループさせるか』を考えるのではなく、宣言的に『どんな結果が欲しいか』を記述するのがコツです。」
生徒
「なるほど。目的をコードに込めるイメージですね。でも、reduceだけは少し使い方が難しい気がしました……。」
先生
「確かにreduceは多機能で強力な分、最初は戸惑うかもしれません。まずは『合計値を出す』というシンプルな用途から始めて、徐々にデータの集約や整形に挑戦してみるといいですよ。慣れてくれば、配列を自由自在に作り変えられるようになります。」
生徒
「分かりました!まずは学んだメソッドを一つずつ自分のプロジェクトで使ってみます。あと、空チェックをlengthでするのも、つい忘れがちなので気をつけます。」
先生
「素晴らしいですね。細かいチェックを怠らないことが、バグの少ない良いプログラムへの第一歩です。他にもsortの挙動の違いなど、JavaScript特有の注意点も忘れずに復習しておいてくださいね。これからも一緒に楽しく学んでいきましょう!」
生徒
「はい、頑張ります!次のレッスンもよろしくお願いします!」