0Pricing
C# Academy · レッスン

Dictionaryの検索

キーと値にすばやくアクセスします。

「Dictionaryの検索」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

キーと値のペア

Dictionary<TKey, TValue> は、一意のキーを値に対応付けます。検索テーブルのようなもので、キーを渡すと値をすばやく取得できます。

ハッシュテーブルを基盤としているため、キーによる値の検索は平均 O(1) で、リストを走査するよりはるかに高速です。

using System.Collections.Generic;

var ages = new Dictionary<string, int>();
ages["Ann"] = 30;
ages["Bob"] = 25;

Dictionary の初期化

コレクション初期化子を使って、Dictionary に初期値を設定できます。各エントリはキーとその値のペアになります。

キーは一意でなければなりません。初期化子で同じキーを2回指定すると、実行時に ArgumentException がスローされます。

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var caps = new Dictionary<string, string> {
            ["FR"] = "Paris",
            ["JP"] = "Tokyo"
        };
        Console.WriteLine(caps["JP"]);
    }
}

キーによる読み取り

インデクサーを使って読み取ります: dict[key]。平均計算量は O(1) です。

ただし、キーが存在しない場合、インデクサーは KeyNotFoundException をスローします。存在しないキーを読み取ることは、Dictionary で最もよくあるバグの一つです。

var ages = new Dictionary<string, int> { ["Ann"] = 30 };
int a = ages["Ann"];      // 30
// int b = ages["Zoe"];   // throws KeyNotFoundException

TryGetValue による安全な検索

TryGetValue は例外を回避します。キーが存在する場合は true を返して out 変数に値を設定し、存在しない場合は false を返します。

これは、存在するかどうかわからない値を検索する際の、慣用的でメモリ割り当てを伴わない方法です。

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var ages = new Dictionary<string, int> { ["Ann"] = 30 };
        if (ages.TryGetValue("Ann", out int v))
            Console.WriteLine(v);
    }
}

ContainsKey とデフォルト値

ContainsKey は値を読み取らずにキーの存在を O(1) で確認します。存在するかどうかだけが必要な場合は、インデクサーで読み取る前に使用してください。

ContainsKey とインデクサーの両方を呼び出すと、キーのハッシュ化が 2 回行われます。TryGetValue なら 1 回で済むため、通常はこちらのほうが高速です。

var ages = new Dictionary<string, int> { ["Ann"] = 30 };
if (ages.ContainsKey("Ann"))
    System.Console.WriteLine(ages["Ann"]);

追加と代入

インデクサー dict[key] = value は、新しいペアを挿入するか、既存のペアを上書きします。Add(key, value) は挿入のみを行い、キーがすでに存在する場合は例外をスローします。

重複キーをエラーにしたい場合は Add を、上書きしても問題ない場合はインデクサーを使用してください。

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var d = new Dictionary<string, int>();
        d["x"] = 1;
        d["x"] = 2;     // overwrite, fine
        Console.WriteLine(d["x"]);
    }
}

エントリの削除

Remove(key) はペアを削除し、キーが存在していた場合は true を返します。平均計算量は O(1) です。

オーバーロードの中には、out パラメーターを通じて削除した値を返すものもあります。削除と値の利用を一度に行いたい場合に便利です。

var d = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };
bool removed = d.Remove("a");   // true
bool again = d.Remove("a");     // false

ペアの反復処理

ループでは KeyValuePair<TKey, TValue> の要素が取得されます。これをキーと値に分解すると、コードをすっきり書けます。

列挙の順序は保証されません。エントリが挿入された順序を決して前提にしないでください。一方だけを反復処理する場合は、Keys または Values を使用してください。

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var d = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };
        foreach (var (key, val) in d)
            Console.WriteLine($"{key}={val}");
    }
}

Dictionary によるカウント

典型的な用途の一つが、出現回数の集計です。各項目について、カウントを増やします。新しい項目の場合は 0 から始めます。

各検索と更新が O(1) であるため、n 個の項目に対してこのパターンの計算量は O(n) です。毎回リストを走査する場合の O(n²) と比べて効率的です。

using System;
using System.Collections.Generic;

class Program {
    static void Main() {
        var counts = new Dictionary<char, int>();
        foreach (char c in "banana")
            counts[c] = counts.GetValueOrDefault(c) + 1;
        Console.WriteLine(counts['a']);
    }
}

キーの等価性が重要

検索では、キーの型の GetHashCode と Equals に依存します。組み込み型と string はそのまま使用できます。

カスタムクラスをキーにする場合は、両方のメソッドをオーバーライドするか、record を使用してください。そうしないと、同じように見える 2 つのキーが異なるハッシュ値になり、検索に失敗します。

var byName = new Dictionary<string, int>(
    System.StringComparer.OrdinalIgnoreCase);
byName["Hi"] = 1;
bool found = byName.ContainsKey("HI"); // true

値の型を選ぶ

値にはリストを含め、任意の型を指定できます。Dictionary<string, List<int>> を使うと、1 つのキーの下に複数の値をまとめられます。

このような構造に値を挿入する場合は、最初に使用するときに内部リストを作成し、その後で値を追加します。これにより、グループ化された複数値のマップを構築できます。

var groups = new Dictionary<string, List<int>>();
void Add(string k, int v) {
    if (!groups.TryGetValue(k, out var list))
        groups[k] = list = new List<int>();
    list.Add(v);
}

確認問題

存在しない可能性があるキーを読み取る最も安全な方法を選んでください。

まとめ

Dictionary<K,V> はハッシュテーブルを基盤とし、キーによる検索、挿入、削除を平均 O(1) で行えます。

例外をスローするインデクサーよりも TryGetValue を優先し、キーが一意になるようにしてください。また、カスタムキー型が適切な等価性とハッシュ化を実装していることを確認してください。反復処理の順序は未定義です。

よくある質問

「Dictionaryの検索」レッスンは無料ですか?

はい。「Dictionaryの検索」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「Dictionaryの検索」で何を学びますか?

キーと値にすばやくアクセスします。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「Dictionaryの検索」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Listを実践する
  2. Dictionaryの検索
  3. HashSetと一意性
  4. コレクションを選ぶ
← C# Academyに戻る