【C#】C#配列とコレクションを解説 - わかりやすい例で解説
プログラミングでは、データを効率よく管理することがとても重要です。そこで使われるのが、配列やコレクションと呼ばれるデータ構造です。これらは、データをグループ化して管理したり、データに素早くアクセスしたりするのに役立ちます。
今回は、C#における配列、リスト、ディクショナリについて、日常生活のたとえを交えながらわかりやすく解説していきます。
この記事で学べること
- 配列(Array)の宣言・初期化・使い方
- リスト(List)の柔軟なデータ管理方法
- ディクショナリ(Dictionary)のキーと値による管理
- 配列・リスト・ディクショナリの使い分け
- LINQを使った便利なデータ操作
配列・リスト・ディクショナリの比較
まず、3つのデータ構造の違いを把握しておきましょう。
| 特徴 | 配列(Array) | リスト(List) | ディクショナリ(Dictionary) |
|---|---|---|---|
| サイズ | 固定 | 可変 | 可変 |
| アクセス方法 | インデックス(数値) | インデックス(数値) | キー(任意の型) |
| 要素の追加 | 不可 | 可能 | 可能 |
| 要素の削除 | 不可 | 可能 | 可能 |
| メモリ効率 | 高い | 中程度 | 低い |
| アクセス速度 | O(1) | O(1) | O(1) |
| 検索速度 | O(n) | O(n) | O(1) |
| 用途 | 固定データの管理 | 動的なリスト管理 | キーによる高速検索 |
配列(Array)
配列は、同じ種類のものを一列に並べて管理するためのものです。たとえば、「冷蔵庫の中に並んでいる飲み物」をイメージしてみましょう。冷蔵庫にはジュースやお茶が決まった数だけ並んでいます。この飲み物たちが配列です。
配列の宣言と初期化
配列は、冷蔵庫に入れる飲み物の種類と数をあらかじめ決めておく必要があります。これが「宣言と初期化」です。
// 冷蔵庫に5本の飲み物を準備する
string[] drinks = { "ジュース", "お茶", "コーラ", "水", "ミルク" };
// 冷蔵庫に3つの空の場所を準備する
string[] foods = new string[3];
ここでは、drinks配列に5種類の飲み物を並べ、foods配列には空の場所を3つ確保しました。
配列の使用方法
冷蔵庫の中の飲み物にアクセスするには、番号(インデックス)を使います。たとえば、最初に並んでいる飲み物を取り出したいときはこうします。
// 一番目の飲み物を取り出す
Console.WriteLine(drinks[0]); // 出力: ジュース
また、新しい飲み物を入れたいときは、次のように空いている場所に入れます。
// 1つ目の空の場所にリンゴを入れる
foods[0] = "リンゴ";
多次元配列
多次元配列は、冷蔵庫の中に棚が2段あるようなイメージです。それぞれの棚に飲み物が並んでいます。
// 2段の棚に飲み物を並べる
string[,] shelves = new string[2, 3] { { "ジュース", "お茶", "コーラ" }, { "水", "ミルク", "炭酸水" } };
この例では、2つの棚にそれぞれ3つの飲み物が並んでいます。
配列の便利なメソッド
配列にはデータ操作に便利なメソッドが用意されています。
string[] drinks = { "ジュース", "お茶", "コーラ", "水", "ミルク" };
// 配列の長さを取得
Console.WriteLine(drinks.Length); // 出力: 5
// 配列をソート
Array.Sort(drinks);
// drinks: { "お茶", "コーラ", "ジュース", "ミルク", "水" }
// 配列を逆順にする
Array.Reverse(drinks);
// 特定の要素を検索
int index = Array.IndexOf(drinks, "コーラ");
Console.WriteLine(index); // コーラの位置を出力
// 配列をクリア(全要素をデフォルト値に)
Array.Clear(drinks, 0, drinks.Length);
リスト
リストは、飲み物を並べた後でも自由に追加や削除ができる可変式の棚です。たとえば、冷蔵庫のスペースがどんどん変わる場合に便利です。
リストの宣言と初期化
リストは、飲み物の数をあらかじめ決めなくても大丈夫です。必要に応じて飲み物をどんどん追加できます。
// 空のリストを作成して、後で飲み物を追加
List<string> drinks = new List<string>();
// 初期値を持つリストを作成
List<string> fruits = new List<string> { "リンゴ", "バナナ", "オレンジ" };
リストの使用方法
リストに飲み物を追加したり削除したりするのは簡単です。リストはサイズが柔軟なので、たとえ冷蔵庫がいっぱいになっても、リストの棚は無限に広げられます。
// リストに飲み物を追加
drinks.Add("ソーダ");
drinks.Add("緑茶");
// リストの中の飲み物を取り出す
Console.WriteLine(drinks[0]); // 出力: ソーダ
// リストから飲み物を削除
drinks.Remove("緑茶");
また、リストの中身を調べて「この飲み物はあるかな?」と確認することもできます。
bool hasSoda = drinks.Contains("ソーダ");
Console.WriteLine(hasSoda); // 出力: True
リストの便利なメソッド
リストには配列よりも多くの便利なメソッドがあります。
List<int> numbers = new List<int> { 5, 2, 8, 1, 9, 3 };
// 要素数を取得
Console.WriteLine(numbers.Count); // 出力: 6
// 特定の位置に要素を挿入
numbers.Insert(0, 10); // 先頭に10を挿入
// 特定の位置の要素を削除
numbers.RemoveAt(0); // 先頭の要素を削除
// ソート
numbers.Sort(); // 昇順: { 1, 2, 3, 5, 8, 9 }
// 逆順にする
numbers.Reverse(); // { 9, 8, 5, 3, 2, 1 }
// 条件に合う要素を検索
int found = numbers.Find(x => x > 5); // 5より大きい最初の要素
Console.WriteLine(found); // 出力: 9
// 条件に合う全ての要素を取得
List<int> filtered = numbers.FindAll(x => x > 3);
// filtered: { 9, 8, 5 }
// 全ての要素を削除
numbers.Clear();
ディクショナリ
ディクショナリは、飲み物のラベルに名前をつけて管理するようなものです。たとえば、「ペットボトルには水」「缶にはジュース」という風にキーと値のペアで管理します。
ディクショナリの宣言と初期化
ディクショナリでは、どの容器に何が入っているかをはっきりさせるために、キーを使って内容物を管理します。
// 空のディクショナリを作成
Dictionary<string, string> drinks = new Dictionary<string, string>();
// 初期値を持つディクショナリを作成
Dictionary<string, string> containers = new Dictionary<string, string>
{
{ "ボトル", "水" },
{ "缶", "ジュース" },
{ "箱", "牛乳" }
};
ディクショナリの使用方法
ディクショナリでは、ラベル(キー)を使って、中身にアクセスできます。
// ラベルに基づいて中身を取り出す
Console.WriteLine(containers["ボトル"]); // 出力: 水
また、新しい容器と中身を追加したり、既存のものを削除することもできます。
// 新しい容器を追加
drinks.Add("ペットボトル", "炭酸水");
// 中身を削除
containers.Remove("缶");
さらに、ディクショナリを使って、どの容器に何が入っているかを確認することもできます。
foreach (KeyValuePair<string, string> container in containers)
{
Console.WriteLine($"{container.Key}には{container.Value}が入っています。");
}
ディクショナリの便利なメソッド
ディクショナリにはキー・値の操作に便利なメソッドがあります。
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 85 },
{ "佐藤", 92 },
{ "鈴木", 78 }
};
// 要素数を取得
Console.WriteLine(scores.Count); // 出力: 3
// キーの存在確認
if (scores.ContainsKey("田中"))
{
Console.WriteLine("田中さんのスコアがあります");
}
// 値の存在確認
if (scores.ContainsValue(92))
{
Console.WriteLine("92点を取った人がいます");
}
// 安全に値を取得(キーが存在しない場合にエラーを避ける)
if (scores.TryGetValue("山田", out int score))
{
Console.WriteLine($"山田さんのスコア: {score}");
}
else
{
Console.WriteLine("山田さんのスコアは登録されていません");
}
// 全てのキーを取得
foreach (string name in scores.Keys)
{
Console.WriteLine(name);
}
// 全ての値を取得
foreach (int value in scores.Values)
{
Console.WriteLine(value);
}
LINQを使ったデータ操作
LINQ(Language Integrated Query)を使うと、配列やコレクションのデータを簡潔に操作できます。
using System.Linq;
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 条件でフィルタリング(偶数だけ取得)
var evens = numbers.Where(x => x % 2 == 0);
// evens: { 2, 4, 6, 8, 10 }
// 変換(各要素を2倍に)
var doubled = numbers.Select(x => x * 2);
// doubled: { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }
// 集計
int sum = numbers.Sum(); // 合計: 55
double avg = numbers.Average(); // 平均: 5.5
int max = numbers.Max(); // 最大: 10
int min = numbers.Min(); // 最小: 1
// 最初の要素、最後の要素
int first = numbers.First(); // 1
int last = numbers.Last(); // 10
// 条件に合う最初の要素
int firstEven = numbers.First(x => x % 2 == 0); // 2
// ソート
var sorted = numbers.OrderBy(x => x); // 昇順
var sortedDesc = numbers.OrderByDescending(x => x); // 降順
// 重複を除去
List<int> withDupes = new List<int> { 1, 2, 2, 3, 3, 3 };
var unique = withDupes.Distinct(); // { 1, 2, 3 }
// 指定した数だけ取得
var firstThree = numbers.Take(3); // { 1, 2, 3 }
var skipThree = numbers.Skip(3); // { 4, 5, 6, 7, 8, 9, 10 }
LINQをディクショナリで使う
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 85 },
{ "佐藤", 92 },
{ "鈴木", 78 },
{ "山田", 95 }
};
// 80点以上の人を抽出
var highScorers = scores.Where(x => x.Value >= 80);
foreach (var person in highScorers)
{
Console.WriteLine($"{person.Key}: {person.Value}点");
}
// 出力: 田中: 85点, 佐藤: 92点, 山田: 95点
// 点数の高い順にソート
var ranked = scores.OrderByDescending(x => x.Value);
// 最高得点者を取得
var topScorer = scores.OrderByDescending(x => x.Value).First();
Console.WriteLine($"トップ: {topScorer.Key} ({topScorer.Value}点)");
// 出力: トップ: 山田 (95点)
使い分けのガイドライン
どのデータ構造を使うべきか迷ったときの目安です。
| シチュエーション | おすすめ | 理由 |
|---|---|---|
| データ数が決まっている | 配列 | メモリ効率が良い |
| データを頻繁に追加・削除する | リスト | サイズ変更が容易 |
| キーで素早く検索したい | ディクショナリ | O(1)で検索可能 |
| 順番が重要 | 配列・リスト | 順序が保証される |
| 重複を許可しない | HashSet | 自動で重複を排除 |
まとめ
C#の配列やコレクションを使うと、プログラム内でのデータ管理が非常に効率的になります。
- 配列は冷蔵庫のように、同じ種類のものを決まった数だけ並べるのに便利です。
- リストは柔軟な棚のように、要素を自由に追加したり削除したりできます。
- ディクショナリはラベル付きの容器のように、キーを使って素早くデータにアクセスできます。
日常生活で使う冷蔵庫や棚のように、プログラムでもこれらのデータ構造をうまく使いこなすことで、効率的で整理されたコードを書けるようになります。
ポイントの振り返り
| データ構造 | 特徴 | 使いどころ |
|---|---|---|
| 配列 | 固定サイズ、高速アクセス | 決まった数のデータ管理 |
| リスト | 可変サイズ、柔軟な操作 | 動的なデータの追加・削除 |
| ディクショナリ | キーによる高速検索 | 名前やIDでのデータ管理 |
| LINQ | 簡潔なデータ操作 | フィルタ、変換、集計 |
参考文献
Recommend
2024-08-19
【C#】C#のデータ型完全ガイド - 基本から高度な型まで詳しく解説
2024-08-21
【C#】信頼性の高いログ処理システムの設計と実装:バッファリング、リトライ、シャットダウン処理まで
2024-08-19
【C#】C#配列とコレクションを解説 - わかりやすい例で解説
2024-08-19
【C#】C#の基礎を解説 - 最初の「Hello, World」プログラム
2024-08-19
【C#】C#制御構文の基本 - 簡単に理解する条件分岐とループの使い方
2024-08-19
【C#】C#とは? - C#の歴史と、概要、具体的な開発事例を解説
2024-08-19
【C#】C#演算子ガイド - 基本から応用までわかりやすく解説