201

どのデータ構造が最も効率的で、いつ/どこでどのデータ構造を使用するかについて頭を悩ませようとしています。

さて、構造がよくわからないだけかもしれませんが、どうILookup(of key, ...)違うのDictionary(of key, list(of ...))

また、どこで使用したいのですかILookup、プログラム速度/メモリ/データアクセスなどの点でどこでより効率的ですか?

4

6 に答える 6

307

2つの重要な違い:

  • Lookup不変です。Yay :)(少なくとも、具象Lookupクラスは不変であり、ILookupインターフェースは変更メンバーを提供しないと思います。もちろん、他の変更可能な実装がある可能性があります。
  • ルックアップに存在しないキーをルックアップすると、の代わりに空のシーケンスが返されますKeyNotFoundException。(したがってTryGetValue、AFAICRはありません。)

効率は同等である可能性がありますDictionary<TKey, GroupingImplementation<TValue>>。たとえば、ルックアップでは舞台裏を使用する場合があります。要件に基づいてそれらから選択してください。個人的には、ルックアップは通常、上記の最初の2つのポイントが原因で、よりも適していることがわかりましたDictionary<TKey, List<TValue>>

実装の詳細として、値に具体的な実装IGrouping<,>が使用されていることに注意してください。これは、などIList<TValue>で使用するのが効率的であることを意味します。Count()ElementAt()

于 2012-11-13T14:33:15.503 に答える
75

誰も実際の最大の違いを述べていないのは興味深いことです(MSDNから直接取得):

ルックアップは辞書に似ています。違いは、ディクショナリがキーを単一の値にマップするのに対し、ルックアップはキーを値のコレクションにマップすることです。

于 2014-06-06T06:10:09.527 に答える
36

aDictionary<Key, List<Value>>Lookup<Key, Value>論理的にはどちらも同様の方法で編成されたデータを保持でき、どちらも同じ程度の効率です。主な違いは、Lookupが不変であるということです。Add()メソッドもパブリックコンストラクターもありません(Jonが述べたように、例外なく存在しないキーをクエリし、グループ化の一部としてキーを使用できます)。

どちらを使用するかは、実際にどのように使用するかによって異なります。絶えず変更されている複数の値へのキーのマップを維持している場合は、Dictionary<Key, List<Value>>変更可能であるため、おそらくaの方が適しています。

ただし、一連のデータがあり、キーごとに整理されたデータの読み取り専用ビューが必要な場合は、ルックアップの作成が非常に簡単で、読み取り専用のスナップショットが得られます。

于 2012-11-13T14:32:14.617 に答える
13

まだ言及されていないもう1つの違いは、Lookup()がnullキーをサポートしていることです。

LookupクラスはILookupインターフェースを実装します。ルックアップは辞書と非常によく似ていますが、複数の値を同じキーにマップでき、nullキーがサポートされている点が異なります。

于 2016-05-20T09:38:41.080 に答える
12

ILookup<K,V>anとaの主な違いはDictionary<K, List<V>>、辞書が変更可能であることです。キーを追加または削除したり、検索されたリストからアイテムを追加または削除したりできます。AnILookup不変であり、一度作成すると変更できません。

両方のメカニズムの基本的な実装は同じか類似しているため、検索速度とメモリフットプリントはほぼ同じになります。

于 2012-11-13T14:32:30.403 に答える
6

例外が選択できない場合は、ルックアップに移動します

と同じくらい効率的な構造を取得しようとしているDictionaryが、入力に重複するキーがないことを確認できない場合は、Lookupより安全です。

別の回答で述べたように、nullキーもサポートし、任意のデータでクエリを実行すると常に有効な結果を返すため、不明な入力に対してより回復力があるように見えます(Dictionaryよりも例外が発生する傾向がありません)。

そして、それをSystem.Linq.Enumerable.ToDictionary関数と比較すると特に当てはまります。

// won't throw
new[] { 1, 1 }.ToLookup(x => x); 

// System.ArgumentException: An item with the same key has already been added.
new[] { 1, 1 }.ToDictionary(x => x);

foreach別の方法は、ループ内に独自の重複キー管理コードを記述することです。

パフォーマンスに関する考慮事項、辞書:明確な勝者

リストが不要で、膨大な数のアイテムを管理する場合Dictionary(または独自のカスタム調整された構造でさえ)、より効率的です。

        Stopwatch stopwatch = new Stopwatch();
        var list = new List<string>();
        for (int i = 0; i < 5000000; ++i)
        {
            list.Add(i.ToString());
        }
        stopwatch.Start();
        var lookup = list.ToLookup(x => x);
        stopwatch.Stop();
        Console.WriteLine("Creation: " + stopwatch.Elapsed);

        // ... Same but for ToDictionary
        var lookup = list.ToDictionary(x => x);
        // ...

各キーのアイテムのリストを維持する必要があるためLookup、辞書よりも低速です(膨大な数のアイテムの場合は約3倍遅くなります)

ルックアップ速度:作成:00:00:01.5760444

辞書の速度:作成:00:00:00.4418833

于 2018-05-03T12:28:16.207 に答える