C#

【C#】Dictionaryクラス 総まとめ

この記事ではC#のDictionaryクラスについて簡単なコードで解説します。

Dictioanryの基本

Dictionaryクラスとは、配列やListクラスのようにオブジェクトをグループ化する仕組みで、ジェネリックコレクションの一種です。

配列やListクラスでは要素番号(インデックス)で要素の値にアクセスするのに対して、Dictionaryクラスはキー(key)と値(value)のペアを持ち、キーにより値にアクセスします。このためキーは重複することはできません。

このようなキーと値を持つ配列を連想配列とも言います。通常の配列のインデックスは数字ですが、連想配列であるDictionaryクラスでは任意の型を持つキーがインデックスの代わりになります。

Dictionaryの宣言と初期化

Dictionaryオブジェクトは下記のように宣言します。

var オブジェクト名 = new Dictionary<Tkey, TValue>();

もちろんvarではなくDictionary<TKey,TValue>でもOKです。

実際の宣言と初期化の方法を見てみましょう。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        //空のDictionaryの宣言と初期化
        var dic1 = new Dictionary<string, double>();

        //宣言と初期化子を使った初期化
        var dic2 = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };
    }
}

上記コードは宣言と初期化をしているだけです。

まずC#でDictionaryクラスを使うためには、2行目のようにusingディレクティブに、
 using System.Collections.Generic;
を記述します。書かない場合には宣言時に完全修飾名が必要です。

9行目では空のDictionaryオブジェクトのインスタンスを生成しています。このDictinaryのキーはstring型、値はdouble型になります。varはDictionary<string, double>とすることももちろんできます。

12~16行目でも同じくDictionaryオブジェクトのインスタンスを生成していますが、13~15行目でキーと値のペアで初期化子を使って初期化しています。

Dictionaryのキーによるアクセス

Dictionaryオブジェクトにはキーによりアクセスします。配列のインデックスの代わりにキーを用いるイメージです。具体的には下記のとおりです。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        string jpn = "Japan";
        Console.WriteLine("{0}の人口は{1}億人です", jpn, dic[jpn]);

        dic[jpn] = 2;
        Console.WriteLine("{0}の人口が{1}億人に増えました", jpn, dic[jpn]);
    }
}

出力結果

Japanの人口は1.261億人です
Japanの人口が2億人に増えました

上記コードの15行目のdic[jpn]でDhictionaryの値にアクセスしています。jpn=”Japan”なので、dic[“Japan”]としているのと同じことです。9行目の初期化子によって、キー”Japan”に対応する値は1.2610となっていますので、出力結果の通りとなります。

17行目のようにキーを指定して値を変更することもできます。

Dictionaryのforeach文による繰り返し処理

次にforeachによりDictionaryオブジェクトの中身を表示してみましょう。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        foreach (var item in dic)
        {
            Console.WriteLine("{0}の人口は{1}億人です", item.Key, item.Value);
        }
    }
}

出力結果

Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です

上記コードの14行目のitemはvarとして型推論していますが、実際にはDictionaryオブジェクトの要素の型はKeyValuePair<TKey, TValue>という型です。この場合にはKeyValuePair<string, double>という型になります。このKeyValuePair<TKey, TValue>型の変数は読み取り専用のKeyプロパティとValueプロパティがあり、それぞれDictionaryオブジェクトの要素のキーと値を取得することができます。

ちなみに次のようにDictionaryオブジェクトの要素(KeyValuePair<TKey, TValue>型)をタプルで受け取ることもできます。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        foreach (var (key, val) in dic)
        {
            Console.WriteLine("{0}の人口は{1}億人です", key, val);
        }
    }
}

出力結果

Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です

上記コードの14行目ではタプルで受け取っています。foreach(var (key, val) in dic)の部分は、
 foreach((string key, double val) in dic)
としても同じです。

ToStringメソッドを使って要素をリストアップする

またリストアップするだけなら、ToString()メソッドも使用できます。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        foreach (var item in dic)
        {
            Console.WriteLine(item.ToString());
        }
    }
}

出力結果

[Japan, 1.261]
[USA, 3.329]
[India, 13.904]

Dictionaryクラスのプロパティ

Countプロパティで要素数を取得する

CountプロパティはDictionaryオブジェクトの要素数を取得します。

下記コードでは14行目で要素数を取得しています。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        Console.WriteLine("{0}の要素数は{1}です", nameof(dic), dic.Count);
    }
}

出力結果

dicの要素数は3です

Keysプロパティでキーを格納したコレクションを取得する

Keysプロパティは、キーを格納したコレクションを返します。このコレクションの型はDictionary<TKey,TValue>.KeyCollection型です。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        var keys = dic.Keys;

        foreach(var key in keys)
        {
            Console.WriteLine(key);
        }
    }
}

出力結果

Japan
USA
India

上記コードの14行目でキーを格納したコレクションを取得し、変数keysに代入しています。ここで変数keysはvarにより型推論されていますが、この場合の型はDictionary<string, double>.KeyCollection型になります。

ここで得たコレクションをforeach文で出力していますが、ここでのkeyはvarで型推論されていますが、これの型はDictionaryオブジェクトのキーの型であるstring型になります。

Valuesプロパティで値を格納したコレクションを取得する

Valuesプロパティは、値を格納したコレクションを返します。このコレクションの型はDictionary<TKey,TValue>.ValueCollection型です。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        var vals = dic.Values;

        foreach(var val in vals)
        {
            Console.WriteLine(val);
        }
    }
}

出力結果

1.261
3.329
13.904

上記コードの14行目でキーを格納したコレクションを取得し、変数keysに代入しています。ここで変数keysはvarにより型推論されていますが、この場合の型はDictionary<string, double>.ValueCollection型になります。

ここで得たコレクションをforeach文で出力していますが、ここでのvalはvarで型推論されていますが、これの型はDictionaryオブジェクトの値の型であるdouble型になります。

Dictionaryクラスのメソッド

Addメソッドで要素を追加する

AddメソッドによりDictionaryオブジェクトに要素(キーと値のペア)を追加できます。Addメソッドの引数は(key, value)になります。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>();
        dic.Add("Japan", 1.2610);
        dic.Add("USA", 3.3290);
        dic.Add("India", 13.9040);

        foreach (var item in dic)
        {
            Console.WriteLine(item.ToString());
        }
    }
}

出力結果

[Japan, 1.261]
[USA, 3.329]
[India, 13.904]

Removeメソッドで指定したキーを持つ要素を削除する

Removeメソッドは2種類あります。

指定したキーを持つ要素を削除する

ひとつめのRemoveメソッドは、単純に指定したキーを持つ要素を削除します。メソッドの引数は一つで、削除する要素のキーを指定します。戻り値はbool型で、正常に削除された場合にはTrueを、それ以外の場合にはFalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        bool flgUSA= dic.Remove("USA");
        bool flgBRZ = dic.Remove("Brazil");

        Console.WriteLine("USAは正常に削除されたので{0}です",flgUSA);
        Console.WriteLine("Brazilは存在しないため削除できないので{0}です",flgBRZ);

        foreach (var (key, val) in dic)
        {
            Console.WriteLine("{0}の人口は{1}億人です", key, val);
        }
    }
}

出力結果

USAは正常に削除されたのでTrueです
Brazilは存在しないため削除できないのでFalseです
Japanの人口は1.261億人です
Indiaの人口は13.904億人です

上記コードでは14,15行目でRemoveメソッドを使用しています。14行目でキーが”USA”の要素を削除しています。削除されているのでRemoveメソッドの戻り値はtrueとなり、flgUSAはtrueとなります。15行目ではキーが”Brazil”の要素を削除しようとしていますが、キーが”Brazil”の要素はありません。キーが存在しないので、正常に削除できていないため、Removeメソッドの戻り値はfalseとなり、flgBRZはfalseとなります。

指定したキーを持つ要素を削除して、その値を取得する

ふたつめのRemoveメソッドは、outキーワードを使って削除した要素の値を受け取る点でひとつめのRemoveメソッドと異なります。

このRemoveメソッドの引数は二つあり、一つ目の引数には削除する要素のキーを指定し、二つ目の引数にはoutキーワードを用いて削除した要素の値を受け取る変数を指定します。戻り値はbool型で、正常に削除された場合にはTrueを、それ以外の場合にはFalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };

        string rmvkey;
        
        rmvkey = "USA";
        bool flgUSA= dic.Remove(rmvkey,out double popUSA);
        Console.WriteLine("USAは正常に削除されたので{0}です", flgUSA);
        Console.WriteLine("削除された{0}の人口は{1}億人でした", rmvkey, popUSA);

        rmvkey = "Brazil";
        bool flgBRZ = dic.Remove(rmvkey, out double popBRZ);
        Console.WriteLine("Brazilは存在しないため削除できないので{0}です",flgBRZ);
        Console.WriteLine("削除できなかった{0}の人口は{1}億人でした", rmvkey, popBRZ);

        foreach (var (key, val) in dic)
        {
            Console.WriteLine("{0}の人口は{1}億人です", key, val);
        }
    }
}

出力結果

USAは正常に削除されたのでTrueです
削除されたUSAの人口は3.329億人でした
Brazilは存在しないため削除できないのでFalseです
削除できなかったBrazilの人口は0億人でした
Japanの人口は1.261億人です
Indiaの人口は13.904億人です

上記コードでは17行目でRemoveメソッドを使用してキー”USA”を持つ要素を削除し、outキーワードを使ってpopUSAに削除された要素の値を受け取っています。正常に削除されているためRemoveメソッドの戻り値はtrueです。戻り値は18行目で、popUSAの値は19行目で表示しています。

次に22行目でキーが”Brazil”の要素を削除しています。しかしキーが”Brazil”の要素は存在しませんので正常に削除できず、Removeメソッドの戻り値はfalseとなります。outキーワードを使ってpopBRZで削除された要素の値を受け取ろうとしていますが、削除できていないので、double型の規定値の0が入ります。戻り値は23行目で、popBRZの値は24行目で表示しています。

Clearメソッドですべての要素を削除する

Clearメソッドでは、すべての要素を削除します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>(){
            { "Japan", 1.2610 },
            { "USA", 3.3290},
            { "India", 13.9040 }
        };
        Console.WriteLine("Clear前の{0}の要素数は{1}です", nameof(dic), dic.Count);
        dic.Clear();
        Console.WriteLine("Clear後の{0}の要素数は{1}です", nameof(dic), dic.Count);
    }
}

出力結果

Clear前のdicの要素数は3です
Clear後のdicの要素数は0です

上記コードでは14行目でClearメソッドを使用しています。15行目でClearメソッド後の要素数を表示していますが、0となっています。

ContainsKeyメソッドでキーの有無を調べる

指定したキーを持つ要素がDictionaryオブジェクトに含まれているかを調べます。引数はひとつで有無を調べるキーを指定します。戻り値はbool型で、指定したキーを持つ要素が存在すればtrueを、存在しない場合にはfalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, string>(){
            { "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" },{"次郎","赤組"}
        };

        string str;

        str = "花子";
        Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsKey(str));

        str = "桃子";
        Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsKey(str));
    }
}

出力結果

花子を検索しました.結果はTrueです.
桃子を検索しました.結果はFalseです.

ContainsValueメソッドで値の有無を調べる

指定した値を持つ要素がDictionaryオブジェクトに含まれているかを調べます。引数はひとつで有無を調べる値を指定します。戻り値はbool型で、指定した値を持つ要素が存在すればtrueを、存在しない場合にはfalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, string>(){
            { "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" },{"次郎","赤組"}
        };

        string str;

        str = "赤組";
        Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsValue(str));

        str = "黄組";
        Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsValue(str));
    }
}

出力結果

赤組を検索しました.結果はTrueです.
黄組を検索しました.結果はFalseです.

GetEnumeratorメソッドによる列挙子の取得とキーと値の列挙

GetEnumeratorメソッドを使って列挙子を取得することができます。下記コードでは、列挙子を使ってキーと値を列挙します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>();
        dic.Add("Japan", 1.2610);
        dic.Add("USA", 3.3290);
        dic.Add("India", 13.9040);

        //列挙子の取得
        var e = dic.GetEnumerator();

        while (e.MoveNext() == true)
        {
            Console.WriteLine("{0}の人口は{1}億人です", e.Current.Key, e.Current.Value);
        }
        e.Dispose();
    }
}

出力結果

Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です

14行目で列挙子eを取得しています。取得直後は、列挙子は最初の要素の前に位置していますので、16行目のMoveNextメソッドで次の要素に移動しています。MoveNextメソッドは、列挙子が次の要素に移動した場合にはtrue、次の要素に移動できなかった場合にはfalseを返します。whileループの条件式はe.MoveNext() == trueとなっているので、次の要素がなくなりfalseとなった時点でループから抜けます。

また18行目のCurrentプロパティでは、列挙子の現在位置の要素を取得します。この要素は、KeyValuePair<TKey, TValue>型なので、読み取り専用のKeyプロパティとValueプロパティでキーと値を取得しています。

20行目のDisposeメソッドでリソースを解放しています。

TryAddメソッドで指定したキーと値の追加を試みる

TryAddメソッドでは、指定したキーと値の追加を試みます。TryAddメソッドの引数は二つあり、ひとつめは追加を試みるキー、ふたつめは追加を試みる値です。戻り値はbool型で、正常にキーと値のペアが追加されればtrueを返し、それ以外の場合にはfalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, string>(){
            { "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" }
        };

        string name, team;
        bool result;

        name = "次郎"; team = "赤組";
        result = dic.TryAdd(name, team);
        if(result) Console.WriteLine("{0}が{1}として正常に追加されました", name , dic[name]);
        else Console.WriteLine("{0}が{1}に追加できませんでした", name, team);


        name = "太郎"; team = "赤組";
        result = dic.TryAdd(name, team);
        if (result) Console.WriteLine("正常に{0}が{1}として追加されました", name, dic[name]);
        else Console.WriteLine("{0}を{1}に追加できませんでした", name, team);
    }
}

出力結果

次郎が赤組として正常に追加されました
太郎を赤組に追加できませんでした

上記コードでは、16行目と22行目でTryAddメソッドを使用しています。16行目では正常にキーと値を追加できるのでtrueを返してます。22行目では、重複したキーがあるので追加できずfalseを返しています。

TryGetValueメソッドで指定したキーを持つ要素の値の取得を試みる

TryGetValueメソッドは、指定したキーを持つ要素の値の取得を試みるメソッドです。引数は2つあり、ひとつめはキーを指定します。ふたつめの引数にはoutキーワードを用いて取得を試みた要素の値を受け取る変数を指定します。戻り値はbool型で、正常に取得できればtrueを、それ以外の場合にはfalseを返します。

コード

using System;
using System.Collections.Generic;

internal class Program
{
    static void Main(string[] args)
    {
        var dic = new Dictionary<string, double>();
        dic.Add("Japan", 1.2610);
        dic.Add("USA", 3.3290);
        dic.Add("India", 13.9040);

        string str;
        bool result;

        str = "USA";
        result = dic.TryGetValue(str, out double popUSA);
        if (result) Console.WriteLine("{0}の人口は{1}億人です", str, popUSA);
        else Console.WriteLine("{0}の人口は取得できませんでした", str);

        str = "Brazil";
        result = dic.TryGetValue(str, out double popBRZ);
        if (result) Console.WriteLine("{0}の人口は{1}億人です", str, popBRZ);
        else Console.WriteLine("{0}の人口は取得できませんでした", str);
    }
}

出力結果

USAの人口は3.329億人です
Brazilの人口は取得できませんでした

上記コードでは、17行目と22行目で値の取得を試みています。17行目では値が取得できたのでresultにはtrueが入ります。22行目ではキーが”Brazil”という要素は存在しないため値は取得できずresultにはfalseが入ります。

終わりに

ここではDictionaryについて説明しました。Dictionaryクラスのキーにはクラスやタプルなども使用できます。使い方によっては便利です。

ABOUT ME
しかすけ
日々是好日。何とか何とか生きてます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です