佐々木屋

技術的なことから趣味まで色々書きます

Dictionaryクラスのソート

ジェネリックコレクションの一つであるDictionaryクラスのソート方法です。
Dictionaryクラスも配列なので、できる方法がたくさんありすぎて困るくらいです。ここでは私がよく使う3つの手法を紹介します。この方法以外でもいっぱいあるので、是非チャレンジしてみて下さい。

以下のDictionaryを考えます。

Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "hoge");
dic.Add(3, "piyo");
dic.Add(2, "fuga");

ソート結果が以下のようになることが目標。

1:hoge
2:fuga
3:piyo


Array.Sortメソッドを利用

多分今回紹介する中で一番高速に処理されます。DictionaryのKeyを一旦配列に変換してソートする方法です。

int[] arr = dic.Keys.ToArray();
Array.Sort(arr);
foreach(int i in arr) {
    Console.WriteLine("{0}:{1}", i.ToString(), dic[i].ToString());
}
Dim arr As Integer() = dic.Keys.ToArray()
Array.Sort(arr)
For Each i As Integer In arr
    Console.WriteLine("{0}:{1}", i.ToString(), dic(i).ToString())
Next


List.Sortメソッドを利用

DictionaryのKeyを一旦Listに変換してソートする方法です。arrayと大して変わりませんが、速度はこちらの方が遅いです。

List<int> lst = dic.Keys.ToList();
lst.Sort();
foreach (int i in lst) {
    Console.WriteLine("{0}:{1}", i.ToString(), dic[i].ToString());
}
Dim lst As List(Of Integer) = dic.Keys.ToList()
lst.Sort()
For Each i As Integer In lst
    Console.WriteLine("{0}:{1}", i.ToString(), dic(i).ToString())
Next

見た目はArrayにする方法と何ら変わりませんが、ListにすることでForeachメソッドが使用できたりとListの恩恵を受けたいときはこちらの方がいいと思います。

LINQのOrderByメソッドを利用

OrderByメソッドでソートした配列を型推論で一時的にコピーして利用する方法です。今回の中で一番遅い処理となりますが、LINQラムダ式を日常的に使用しているなら感覚的に一番簡単だと思います。私がやるなら(さほど大きなデータでなければ)これです。

var sdic = dic.OrderBy((x) => x.Key);
foreach (var v in sdic) {
    Console.WriteLine("{0}:{1}", v.Key, v.Value);
}
Dim sdic = dic.OrderBy(Function(x) x.Key)
For Each v In sdic
    Console.WriteLine("{0}:{1}", v.Key, v.Value)
Next