Dictionaryって使っていますか?
C#では連想配列をDictionaryクラスで扱うことが可能です。連想配列ではKeyと呼ばれるインデックス番号の代わりに使われる名前と、Valueと呼ばれる値をセットで扱います。
この記事では、Dictionaryについて
- Dictionaryとは
- Dictionaryの宣言、定義、初期化
- Addで要素を追加
- foreachで要素を取得する方法
- KeyでValueを取得する方法
- コピーする方法
- 要素を検索する方法
- 要素をソートする方法
- Listとの相互変換
など基本的な内容から、応用的な内容についても解説していきます。
今回はDictionaryについて、使い方をわかりやすく解説します!
Dictionaryとは
Dictionaryでは、Keyと呼ばれるインデックス番号の代わりに使われる名前と、Valueと呼ばれる値をセットで扱います。
KeyとValueをセットで扱う配列のことを連想配列といいます。
C#で連想配列を扱うためのクラスがDictionaryクラスです。DictionaryクラスではKeyを使ってValueの値を取得します。
ちなみに、Keyの値を重複させることはできませんので、注意しましょう!
Listとの違いについて
Listはインデックス番号を使って要素の値を取得します。
これに対して、DictionaryではKeyの値を使ってValueの値を取得するので、数値以外の文字列などを指定することで、セットの値を取得します。
項目とその値というように、セットでデータを扱う必要がある場合に使用します。
Dictionaryの宣言、定義、初期化
Dictionaryは以下のように宣言、定義します。
Dictionary<Keyの型名, Valueの型名> オブジェクト名 = new Dictionary<Keyの型名, Valueの型名>()
Dictionaryクラスを使用するには、usingを使ってSystem.Collections.Genericクラスを呼び出しておく必要があります。
また以下のように記述することもできます。
var オブジェクト名 = new Dictionary<Keyの型名, Valueの型名>()
宣言、定義と同時に初期化することも可能です。
var オブジェクト名 = new Dictionary<Keyの型名, Valueの型名>() { {Key0, Value0}, {Key1, Value1}, ・・・・・・ };
Addで要素を追加
要素を追加するには、Addメソッドを使用します。
Addメソッドは以下のように定義されています。
public void Add( TKey key, TValue value )
引数keyでは追加する要素のキーを指定します。引数valueでは追加する要素の値を指定します。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); } } }
サンプルコードの実行結果は、次にご紹介するforeachを使って出力表示するので、そちらで解説しますね!
ちなみに、同じKeyの値の要素を追加するとこはできません。
注意しましょう!
foreachで要素を取得する方法
foreachで要素を取得する方法についてご紹介します。
KeyとValue両方を取得する方法
KeyValuePair構造体を使って、KeyとValueの両方を取得します。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); foreach(KeyValuePair<string, string> item in myTable) { Console.WriteLine("[{0}:{1}]", item.Key, item.Value); } Console.ReadKey(); } } }
実行結果:
[Hokkaido:Sapporo] [Iwate:Morioka] [Miyagi:Sendai]
Keyのみを取得する方法
DictionaryからKeyのみを取得するにはKeysプロパティを使用します。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); foreach(string Key in myTable.Keys) { Console.WriteLine(Key); } Console.ReadKey(); } } }
実行結果:
Hokkaido Iwate Miyagi
Valueのみを取得する方法
DictionaryからValueのみを取得するにはValuesプロパティを使用します。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); foreach(string Value in myTable.Values) { Console.WriteLine(Value); } Console.ReadKey(); } } }
実行結果:
Sapporo Morioka Sendai
KeyでValueを取得する方法
Dictionaryの特徴はインデックス番号ではなく、Keyとなる文字列などでもValueの値を取得できるところでした。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); string str = "Iwate"; Console.WriteLine("[{0}:{1}]", str, myTable[str]); Console.ReadKey(); } } }
実行結果:
[Iwate:Morioka]
コピーする方法
Dictionaryのオブジェクトをコピーしたい場合があります。
そんな場合にはコピー先のオブジェクトの宣言、定義時にコンストラクタの引数にコピー元のオブジェクトを指定すればコピーすることができます。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable1 = new Dictionary<string, string>(); myTable1.Add("Hokkaido", "Sapporo"); myTable1.Add("Iwate", "Morioka"); myTable1.Add("Miyagi", "Sendai"); // コンストラクタの引数にコピー元のオブジェクトを指定 var myTable2 = new Dictionary<string, string>(myTable1); foreach(KeyValuePair<string, string> item in myTable2) { Console.WriteLine("[{0}:{1}]", item.Key, item.Value); } Console.ReadKey(); } } }
実行結果:
[Hokkaido:Sapporo] [Iwate:Morioka] [Miyagi:Sendai]
要素を検索する方法
Dictionaryの要素のKeyもしはValueに指定の値が含まれているか検索することができます。
Keyの場合とValueの場合、それぞれ確認してみましょう。
Keyを検索する方法
ContainsKeyメソッドを使います。
ContainsKeyメソッドは以下のように定義されています。
public bool ContainsKey( TKey key )
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); string str = "Iwate"; if(myTable.ContainsKey(str)) { Console.WriteLine("{0}はすでにKeyに使われています", str); } else { Console.WriteLine("{0}はKeyに使われていません", str); } Console.ReadKey(); } } }
実行結果:
IwateはすでにKeyに使われています
Valueを検索する方法
ContainsValueメソッドを使います。
ContainsValueメソッドは以下のように定義されています。
public bool ContainsValue( TValue value )
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); string str = "Sendai"; if(myTable.ContainsValue(str)) { Console.WriteLine("{0}はすでにValueに使われています", str); } else { Console.WriteLine("{0}はValueに使われていません", str); } Console.ReadKey(); } } }
実行結果:
SendaiはすでにValueに使われています
要素をソートする方法
Dictionaryの要素をソートするには、LINQのOrderByメソッドを使う方法やKeyValuePair構造体のListを使う方法などがあります。
LINQを使う方法
LINQのOrderByメソッドを使って、引数にラムダ式で記述すると簡単にソートすることができます。
using System; using System.Collections.Generic; using System.Linq; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); var newTable = myTable.OrderBy(x => x.Value); foreach(KeyValuePair<string, string> item in newTable) { Console.WriteLine("[{0}:{1}]", item.Key, item.Value); } Console.ReadKey(); } } }
実行結果:
[Iwate:Morioka] [Hokkaido:Sapporo] [Miyagi:Sendai]
このサンプルコードでは、DictionaryオブジェクトmyTableのValueの要素で昇順にソートをしています。
LINQのOrderByメソッドを使ってソートしていますが、引数の一部をx.Keyと変更することでKeyの要素でソートすることもできます。
KeyValuePairのListを使う方法
foreachでKey、Valueともに取得する際に使用したKeyValuePair構造体を要素の型にしてリストを作成することができます。
リストが作成できたら、リストとしてソートすることができるので便利です。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); var list = new List<KeyValuePair<string, string>>(myTable); list.Sort((a, b) => b.Key.CompareTo(a.Key)); foreach(var item in list) { Console.WriteLine("[{0}:{1}]", item.Key, item.Value); } Console.ReadKey(); } } }
実行結果:
[Miyagi:Sendai] [Iwate:Morioka] [Hokkaido:Sapporo]
このサンプルコードでは、KeyValuePair構造体を要素の型にしてListのオブジェクトlistを作成しています。
listからSortメソッドを呼び出し、引数にラムダ式を指定してKeyの要素で逆順にソートしています。この場合もラムダ式の一部をb.Value.CompareTo(a.Value)と変更することで、Valueでソートすることも可能です。
List型のオブジェクトの場合、今回ご紹介したラムダ式でのソートの他に、デリゲートを使う方法やCompareメソッド、CompareToメソッドを使う方法のように多くの方法で自由にカスタマイズしてソートを行うこともできます。
詳しくはこちらのサイトで解説しているので、ぜひ参考にしてください。
Listとの相互変換
先ほどの要素のソートでご紹介した場合のように、Dictionary型のオブジェクトをList型に変換すると便利な場合があります。
逆にList型のオブジェクトをDictionary型に変換したい場合もあります。
それぞれに変換する方法についてみていきましょう。
DictionaryからListへ変換
DictionaryのKeyやValueをListへ変換する方法についてみていきましょう。
DictionaryのKeysプロパティやValuesプロパティを使ってKeyの値のみやValueの値のみを取得することができました。
これをList型のオブジェクトを宣言、定義する際のコンストラクタの引数に指定することでコピーを作成することができます。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; namespace Sample { class Sample { static void Main() { var myTable = new Dictionary<string, string>(); myTable.Add("Hokkaido", "Sapporo"); myTable.Add("Iwate", "Morioka"); myTable.Add("Miyagi", "Sendai"); var kList = new List<string>(myTable.Keys); var vList = new List<string>(myTable.Values); Console.WriteLine("[{0}]", string.Join(", ", kList)); Console.WriteLine("[{0}]", string.Join(", ", vList)); Console.ReadKey(); } } }
実行結果:
[Hokkaido, Iwate, Miyagi] [Sapporo, Morioka, Sendai]
ListからDictionaryへ変換
2つのListからDictionaryへ変換する方法についてご紹介します。
LINQのZipメソッドを使って2つのListの要素をプロパティに持つ匿名型のシーケンスを作ります。
それをToDictionaryメソッドでDictionary型に変換します。
サンプルコードで確認しましょう。
using System; using System.Collections.Generic; using System.Linq; namespace Sample { class Sample { static void Main() { var kList = new List<string>(); kList.Add("Hokkaido"); kList.Add("Iwate"); kList.Add("Miyagi"); var vList = new List<string>(); vList.Add("Sapporo"); vList.Add("Morioka"); vList.Add("Sendai"); Dictionary<string, string> myTable = kList.Zip(vList, (k, v) => new { k, v }).ToDictionary(a => a.k, a => a.v); foreach(KeyValuePair<string, string> item in myTable) { Console.WriteLine("[{0}:{1}]", item.Key, item.Value); } Console.ReadKey(); } } }
実行結果:
[Hokkaido:Sapporo] [Iwate:Morioka] [Miyagi:Sendai]
まとめ
ここでは、Dictionaryについて説明しました。
Dictionaryの特徴はKeyとValueをセットで扱うことでした。Listのようにインデックス番号ではなく、Keyに指定した文字列などでValueの値を取得することができます。
使いこなすことができるように、この記事を何度も参考にして下さいね!