読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET 絡みのメモを公開しています。

Linq入門記-14 (LINQ To Object, 変換演算子, ToDictionary)

C# Linq


前回に引き続き、変換演算子についてです。
今回は、ToDictionaryメソッドです。

ToDictionaryメソッドは、文字通り結果をDictionaryに変換してくれます。
個人的には、よく利用するメソッドです。


前回までのToArrayやToListと違い、ToDictionaryは引数を与える必要があります。
よく利用するのは、以下の書式です。

public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
)

keySelectorにて、どの値をキーとするのかを指定します。
上記の呼び出しの場合、Dictionaryの値には、対象オブジェクト自身(TSource)が設定されます。


キーと値の両方の抽出方法を指定する場合は、以下の書式を利用します。

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, TElement> elementSelector
)

keySelectorにてキーを、elementSelectorにて値を指定します。


後、IEqualityComparerを指定するオーバーロードも存在するのですが
それは割愛します。


以下、サンプルです。

    #region LinqSamples-14
    public class LinqSamples14 : IExecutable
    {
        class Person
        {
            public int Id { get; set; }
            public string Name { get; set; }
                
            public override string ToString()
            {
                return string.Format("[{0}, {1}]", Id, Name);
            }
        }
        
        public void Execute()
        {
            var persons = new List<Person>
            {
                 new Person{ Id = 1, Name = "gsf_zero1" }
                ,new Person{ Id = 2, Name = "gsf_zero2" }
                ,new Person{ Id = 3, Name = "gsf_zero3" }
                ,new Person{ Id = 4, Name = "gsf_zero4" }
                ,new Person{ Id = 5, Name = "gsf_zero5" }
            };
            
            var query = from   aPerson in persons
                        where  (aPerson.Id % 2) != 0
                        select aPerson;
            
            Console.WriteLine("============ クエリを表示 ============");
            foreach(var aPerson in query)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
            
            //
            // ToDictionaryを利用して、明示的にマップに変換.
            // (このタイミングでクエリが評価され、結果が構築される。)
            //
            // ToDictionaryは、キー要素を抽出するための引数を要求する。(keySelector)
            // 引数にkeySelectorのみを指定している場合、マップの値はそのオブジェクト自身となる。
            //     キー:int32型 (Person.Id)
            //     値 :Personオブジェクト
            //
            // このほかにも、elementSelectorを指定するオーバーロードも存在する。
            //
            Dictionary<int, Person> filteredPersons = query.ToDictionary(item => item.Id);
            
            Console.WriteLine("============ ToDictionaryで作成したリストを表示 ============");
            foreach(var pair in filteredPersons)
            {
                Console.WriteLine("KEY={0}, VALUE={1}", pair.Key, pair.Value);
            }
            
            //
            // 元のリストを変更.
            //
            persons.Add(new Person{ Id = 6, Name = "gsf_zero6" });
            persons.Add(new Person{ Id = 7, Name = "gsf_zero7" });
            
            //
            // もう一度、各結果を表示.
            //
            Console.WriteLine("============ クエリを表示(2回目) ============");
            foreach(var aPerson in query)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
            
            Console.WriteLine("============ ToDictionaryで作成したリストを表示 (2回目)============");
            foreach(var pair in filteredPersons)
            {
                Console.WriteLine("KEY={0}, VALUE={1}", pair.Key, pair.Value);
            }
            
            //
            // ToDictionaryメソッドにkeySelectorとelementSelectorを指定したバージョン.
            //
            Console.WriteLine("============ keySelectorとelementSelectorの両方を指定したバージョン ============");
            foreach (var pair in query.ToDictionary(item => item.Id, item => string.Format("{0}_{1}", item.Id, item.Name)))
            {
                Console.WriteLine("KEY={0}, VALUE={1}", pair.Key, pair.Value);
            }
        }
    }
    #endregion


出力結果は、以下のようになります。

  ============ クエリを表示 ============
  ID=1, NAME=gsf_zero1
  ID=3, NAME=gsf_zero3
  ID=5, NAME=gsf_zero5
  ============ ToDictionaryで作成したリストを表示 ============
  KEY=1, VALUE=[1, gsf_zero1]
  KEY=3, VALUE=[3, gsf_zero3]
  KEY=5, VALUE=[5, gsf_zero5]
  ============ クエリを表示(2回目) ============
  ID=1, NAME=gsf_zero1
  ID=3, NAME=gsf_zero3
  ID=5, NAME=gsf_zero5
  ID=7, NAME=gsf_zero7
  ============ ToDictionaryで作成したリストを表示 (2回目)============
  KEY=1, VALUE=[1, gsf_zero1]
  KEY=3, VALUE=[3, gsf_zero3]
  KEY=5, VALUE=[5, gsf_zero5]
  ============ keySelectorとelementSelectorの両方を指定したバージョン ============
  KEY=1, VALUE=1_gsf_zero1
  KEY=3, VALUE=3_gsf_zero3
  KEY=5, VALUE=5_gsf_zero5
  KEY=7, VALUE=7_gsf_zero7