MSDNはLookupを次のように説明しています:
はに
Lookup<TKey, TElement>
似ていDictionary<TKey, TValue>
ます。違いは、 Dictionary <TKey、TValue>がキーを単一の値にマップするのに対し、 Lookup <TKey、TElement>はキーを値のコレクションにマップすることです。
その説明は特に役に立ちません。Lookupは何に使用されますか?
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
、これらの宣言のほとんどは通常のコードで使用します。)
Lookup<,>
は、Add
用途が限られている(たとえば、メソッドがない)不変のコレクションです。さらに、存在しないキーでルックアップを行うと、例外ではなく空のシーケンスを取得するという意味での汎用コレクションではありません。これは、linqなどの特別なコンテキストでのみ意味があります。これは、MSがクラスのパブリックコンストラクターを提供していないという事実とよく合います。
これについて考える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
}
}
}
の用途の1つは、Lookup
を逆にすること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
すでににあるキーは使用できないため、2行目に例外がスローされますDictionary
。
[もちろん、他の単一のデータ構造を使用して両方向でルックアップを実行したい場合もあります。この例では、後者が変更されるたびにLookup
からを再生成する必要がありDictionary
ます。しかし、一部のデータについては、それが適切なソリューションになる可能性があります。]
電話帳の内容を保持するデータ構造を作成しているとしましょう。lastName、firstNameの順にキーを設定します。多くの人が同じ名前を持つことができるので、ここで辞書を使用するのは危険です。したがって、ディクショナリは常に、最大で1つの値にマッピングされます。
Lookupは潜在的にいくつかの値にマップされます。
Lookup ["Smith"] ["John"]は、10億サイズのコレクションになります。
Lookup["Smith"]["John"]
か?