【C#】C#配列とコレクションを解説 - わかりやすい例で解説

PUBLISHED 2024-08-19

プログラミングでは、データを効率よく管理することがとても重要です。そこで使われるのが、配列コレクションと呼ばれるデータ構造です。これらは、データをグループ化して管理したり、データに素早くアクセスしたりするのに役立ちます。

今回は、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簡潔なデータ操作フィルタ、変換、集計

参考文献

CATEGORY
TAGS
円