MSDNはLookupを次のように説明しています。
Lookup<TKey, TElement>
はDictionary<TKey, TValue>
に似ています。違いは、Dictionary <TKey、TValue>はキーを単一の値にマッピングするのに対して、Lookup <TKey、 TElement>は、キーを値のコレクションにマップします。
私はその説明が特に役立つとは思わない。 Lookupは何に使用されますか?
IGrouping
と辞書のクロスです。キーによってアイテムをグループ化できますが、そのキーを介して効率的な方法でそれらにアクセスできます(すべてを繰り返し処理するのではなく、GroupBy
でできます)。
たとえば、.NETタイプのロードを取得し、ネームスペースによるルックアップを構築することができます...その後、特定のネームスペース内のすべてのタイプを非常に簡単に取得できます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
public class Test
{
static void Main()
{
// Just types covering some different assemblies
Type[] sampleTypes = new[] { typeof(List<>), typeof(string),
typeof(Enumerable), typeof(XmlReader) };
// All the types in those assemblies
IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly)
.SelectMany(a => a.GetTypes());
// Grouped by namespace, but indexable
ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace);
foreach (Type type in lookup["System"])
{
Console.WriteLine("{0}: {1}",
type.FullName, type.Assembly.GetName().Name);
}
}
}
(通常のコードでは、これらの宣言のほとんどにvar
を通常使用します。)
それについて考える1つの方法はこれです:Lookup<TKey, TElement>
はDictionary<TKey, Collection<TElement>>
に似ています。基本的に、ゼロ以上の要素のリストは、同じキーを介して返されます。
namespace LookupSample
{
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
names.Add("Smith");
names.Add("Stevenson");
names.Add("Jones");
ILookup<char, string> namesByInitial = names.ToLookup((n) => n[0]);
// count the names
Console.WriteLine("J's: {0}", namesByInitial['J'].Count()); // 1
Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); // 2
Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); // 0, does not throw
}
}
}
Lookup
の用途の1つは、Dictionary
を逆にすることです。
電話帳がDictionary
として実装されており、それぞれの名前が電話番号に関連付けられた一連の(一意の)名前をキーとしているとします。ただし、名前の異なる2人が同じ電話番号を共有する場合があります。これはDictionary
の問題ではありません。2つのキーが同じ値に対応していることを気にしません。
ここで、特定の電話番号が誰に属しているかを検索する方法が必要です。 Lookup
を作成し、KeyValuePairs
からDictionary
をすべて追加しますが、値をキーとして、キーを値として逆方向に追加します。これで、電話番号を照会し、その電話番号を持つすべての人々の名前のリストを取得できます。同じデータを使用してDictionary
を構築すると、データがドロップされます(または、その方法によっては失敗します)。
dictionary["555-6593"] = "Dr. Emmett Brown";
dictionary["555-6593"] = "Marty McFly";
は、2番目のエントリが最初のエントリを上書きすることを意味します-ドキュメントはリストされなくなります。
同じデータをわずかに異なる方法で書き込もうとしています:
dictionary.Add("555-6593", "Dr. Emmett Brown");
dictionary.Add("555-6593", "Marty McFly");
既にAdd
にあるキーをDictionary
できないため、2行目に例外がスローされます。
[もちろん、他の単一のデータ構造を使用して両方向などのルックアップを行うこともできます。この例は、後者が変更されるたびにLookup
からDictionary
を再生成する必要があることを意味します。しかし、一部のデータでは、適切なソリューションになる可能性があります。]
私はそれを前にうまく使ったことがありませんが、ここに私の行くことがあります:
Lookup<TKey, TElement>
は、一意制約のないテーブルの(リレーショナル)データベースインデックスとほとんど同じように動作します。他の場所と同じ場所で使用してください。
このように議論できると思います。電話帳の内容を保持するデータ構造を作成していると想像してください。 lastNameでキーを入力し、次にfirstNameでキーを入力します。多くの人が同じ名前を持つことができるため、ここで辞書を使用すると危険です。したがって、ディクショナリは常に最大で1つの値にマップされます。
Lookupは、潜在的にいくつかの値にマップされます。
Lookup ["Smith"] ["John"]は、サイズが10億のコレクションになります。