チュートリアル

C#基礎:配列とコレクション

CSharp入門配列コレクション
広告エリア

配列

配列の宣言と初期化

// 宣言と初期化
int[] numbers = new int[5];  // 要素数5の配列
numbers[0] = 10;
numbers[1] = 20;

// 初期値付き
int[] values = { 1, 2, 3, 4, 5 };
int[] values2 = new int[] { 1, 2, 3, 4, 5 };

// 配列の長さ
Console.WriteLine(values.Length);  // 5

配列の操作

int[] numbers = { 1, 2, 3, 4, 5 };

// 要素へのアクセス
Console.WriteLine(numbers[0]);  // 1
Console.WriteLine(numbers[^1]); // 5(末尾から)

// 範囲アクセス
int[] slice = numbers[1..3];    // { 2, 3 }
int[] fromStart = numbers[..3]; // { 1, 2, 3 }
int[] toEnd = numbers[2..];     // { 3, 4, 5 }

// ループ
foreach (int num in numbers)
{
    Console.WriteLine(num);
}

多次元配列

// 2次元配列
int[,] matrix = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

Console.WriteLine(matrix[1, 2]);  // 6
Console.WriteLine(matrix.GetLength(0));  // 3(行数)
Console.WriteLine(matrix.GetLength(1));  // 3(列数)

// ジャグ配列(配列の配列)
int[][] jagged = new int[3][];
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5 };
jagged[2] = new int[] { 6 };

Array クラス

int[] numbers = { 3, 1, 4, 1, 5, 9, 2, 6 };

// ソート
Array.Sort(numbers);
Console.WriteLine(string.Join(", ", numbers));
// 1, 1, 2, 3, 4, 5, 6, 9

// 検索
int index = Array.IndexOf(numbers, 4);  // 4
int binaryIndex = Array.BinarySearch(numbers, 5);  // 5

// 反転
Array.Reverse(numbers);

// コピー
int[] copy = new int[numbers.Length];
Array.Copy(numbers, copy, numbers.Length);

// 埋める
Array.Fill(numbers, 0);

List

// 宣言
List<string> fruits = new List<string>();
List<string> fruits2 = new() { "apple", "banana" };  // C# 9

// 追加
fruits.Add("apple");
fruits.Add("banana");
fruits.AddRange(new[] { "orange", "grape" });
fruits.Insert(1, "melon");  // インデックス指定

// 取得
string first = fruits[0];
string last = fruits[^1];

// 更新
fruits[0] = "kiwi";

// 削除
fruits.Remove("banana");    // 値で削除
fruits.RemoveAt(0);         // インデックスで削除
fruits.RemoveAll(f => f.StartsWith("o"));  // 条件で削除

// 検索
bool hasApple = fruits.Contains("apple");
int index = fruits.IndexOf("orange");
string found = fruits.Find(f => f.Length > 5);

// サイズ
int count = fruits.Count;
bool isEmpty = fruits.Count == 0;

// クリア
fruits.Clear();

Dictionary<TKey, TValue>

// 宣言
var scores = new Dictionary<string, int>();
var scores2 = new Dictionary<string, int>
{
    ["太郎"] = 85,
    ["花子"] = 92
};

// 追加
scores["太郎"] = 85;
scores.Add("次郎", 78);  // キーが存在するとエラー
scores.TryAdd("三郎", 88);  // 安全な追加

// 取得
int taroScore = scores["太郎"];
if (scores.TryGetValue("花子", out int hanakoScore))
{
    Console.WriteLine(hanakoScore);
}
int unknownScore = scores.GetValueOrDefault("不明", 0);

// 更新
scores["太郎"] = 90;

// 削除
scores.Remove("次郎");

// 存在確認
bool hasTaro = scores.ContainsKey("太郎");
bool has100 = scores.ContainsValue(100);

// 走査
foreach (var (key, value) in scores)
{
    Console.WriteLine($"{key}: {value}");
}

HashSet

var colors = new HashSet<string>();

// 追加
colors.Add("red");
colors.Add("green");
colors.Add("blue");
colors.Add("red");  // 重複は無視

Console.WriteLine(colors.Count);  // 3

// 削除
colors.Remove("green");

// 存在確認
bool hasRed = colors.Contains("red");

// 集合演算
var set1 = new HashSet<int> { 1, 2, 3, 4 };
var set2 = new HashSet<int> { 3, 4, 5, 6 };

var union = new HashSet<int>(set1);
union.UnionWith(set2);  // { 1, 2, 3, 4, 5, 6 }

var intersection = new HashSet<int>(set1);
intersection.IntersectWith(set2);  // { 3, 4 }

var difference = new HashSet<int>(set1);
difference.ExceptWith(set2);  // { 1, 2 }

Queue と Stack

// Queue(先入れ先出し)
var queue = new Queue<string>();
queue.Enqueue("first");
queue.Enqueue("second");
queue.Enqueue("third");

string first = queue.Dequeue();  // "first"
string peek = queue.Peek();      // "second"(取り出さない)

// Stack(後入れ先出し)
var stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);

int top = stack.Pop();   // 3
int peekTop = stack.Peek();  // 2

LINQ

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// クエリ構文
var evenQuery = from n in numbers
                where n % 2 == 0
                select n * 2;

// メソッド構文
var evens = numbers.Where(n => n % 2 == 0);
var doubled = numbers.Select(n => n * 2);
var ordered = numbers.OrderByDescending(n => n);

// 集計
int sum = numbers.Sum();
double avg = numbers.Average();
int max = numbers.Max();
int min = numbers.Min();

// 変換
List<int> list = numbers.ToList();
int[] array = numbers.ToArray();
Dictionary<int, int> dict = numbers.ToDictionary(n => n, n => n * n);

// 要素取得
int firstEven = numbers.First(n => n % 2 == 0);
int? notFound = numbers.FirstOrDefault(n => n > 100);
int single = numbers.Single(n => n == 5);

// 判定
bool hasEven = numbers.Any(n => n % 2 == 0);
bool allPositive = numbers.All(n => n > 0);

// グループ化
var grouped = numbers.GroupBy(n => n % 2 == 0 ? "偶数" : "奇数");

不変コレクション

using System.Collections.Immutable;

// 不変リスト
ImmutableList<int> immutableList = ImmutableList.Create(1, 2, 3);
ImmutableList<int> newList = immutableList.Add(4);  // 新しいリストを返す

// 不変ディクショナリ
var immutableDict = ImmutableDictionary<string, int>.Empty
    .Add("one", 1)
    .Add("two", 2);

実践例:学生成績管理

record Student(string Name, int Score);

var students = new List<Student>
{
    new("太郎", 85),
    new("花子", 92),
    new("次郎", 78),
    new("三郎", 92),
    new("四郎", 65)
};

// 平均点
double average = students.Average(s => s.Score);
Console.WriteLine($"平均点: {average:F1}");

// 最高点と最低点
var top = students.MaxBy(s => s.Score);
var bottom = students.MinBy(s => s.Score);

// 成績でグループ化
var graded = students
    .Select(s => new { s.Name, s.Score, Grade = GetGrade(s.Score) })
    .GroupBy(s => s.Grade)
    .OrderBy(g => g.Key);

foreach (var group in graded)
{
    Console.WriteLine($"--- {group.Key} ---");
    foreach (var student in group)
    {
        Console.WriteLine($"  {student.Name}: {student.Score}点");
    }
}

static string GetGrade(int score) => score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    _ => "F"
};

まとめ

  • 配列は固定長、Arrayクラスでユーティリティ操作
  • List<T>は可変長リスト
  • Dictionary<K,V>はキーと値のペア
  • HashSet<T>は重複なし
  • Queue<T>/Stack<T>でFIFO/LIFO
  • LINQで宣言的なデータ処理
  • 範囲演算子..とインデックス^でスライス

次回はクラスについて詳しく学びます。

広告エリア