Lookup () ve Dictionary (Of list ()) arasındaki fark


165

Hangi veri yapılarının en verimli ve ne zaman / nerede hangilerinin kullanılacağı konusunda kafamı sarmaya çalışıyorum.

Şimdi, ben sadece yapıları yeterince iyi anlamıyorum, ama a'dan nasıl ILookup(of key, ...)farklı olabilir Dictionary(of key, list(of ...))?

Ayrıca nerede kullanmak ILookupisterdim ve nerede program hızı / bellek / veri erişimi, vb açısından daha verimli olurdu?


1
kişi arama telt-telement'in ne
nawfal

Yanıtlar:


255

İki önemli fark:

  • Lookupdeğişmez. Yay :) (En azından somut Lookupsınıfın değişmez olduğuna inanıyorum ve ILookuparayüz mutasyona uğrayan üye sağlamıyor. Elbette başka değişebilir uygulamalar da olabilir .)
  • Aramada bulunmayan bir anahtarı aradığınızda, a yerine boş bir sıra elde edersiniz KeyNotFoundException. (Dolayısıyla hayır TryGetValue, AFAICR.)

Verimlilik açısından eşdeğer olmaları muhtemeldir - örneğin, arama Dictionary<TKey, GroupingImplementation<TValue>>perde arkasında kullanılabilir . İhtiyaçlarınıza göre aralarından seçim yapın. Şahsen, araştırmanın genellikle Dictionary<TKey, List<TValue>>yukarıdaki ilk iki noktadan dolayı genellikle a'dan daha uygun olduğunu düşünüyorum .

Bir uygulama detaylı olarak, somut uygulama bu Not IGrouping<,>değerleri uygular için kullanılan IList<TValue>bu kullanmak üzere etkin olduğunu, hangi araçlar Count(), ElementAt()vs.


Varolmayan bir anahtar araması, bir istisna yerine boş bir sıra ile sonuçlanırsa, genel amaçlı bir toplama imo olarak kullanılamaz. Linq sorgularının bir yan ürünü olan değişmez bir koleksiyon durumunda biraz sorun yok.
nawfal

@nawfal - Lookups tam da bunun için. Gönderen msdn : "Sen bir nesne olduğunu uygular IEnumerable <T> üzerinde ToLookup arayarak Lookup <TKey, TElement> bir örneğini oluşturabilir."
Niall Connaughton

50

Kimsenin gerçek en büyük farkı belirtmemesi ilginçtir (doğrudan MSDN'den alınmıştır ):

Arama, sözlüğe benzer. Aradaki fark, bir Sözlük'ün anahtarları tek değerlerle eşleştirmesidir, Arama ise anahtarları değer koleksiyonlarıyla eşleştirir.


51
Soruyu kontrol edin: Arama <TKey, TValue> ve Sözlük <TKey, Liste <TValue>> arasındaki farkla ilgilidir, böylece bu fark zaten açıktır.
Martao

5
@Martao bazı insanlar aramalar ve sözlükler arasındaki farkı anlamak için googling yaparken bu soruyu bulur. Bu cevap gerçekten faydalı.
jakubiszon

34

Hem a Dictionary<Key, List<Value>>hem de Lookup<Key, Value>mantıksal olarak verileri benzer bir şekilde düzenleyebilir ve her ikisi de aynı verimlilik düzeyindedir. Temel fark Lookupdeğişmezdir: hiçbir Add()yöntemi ve kamu kurucusu yoktur (ve Jon'un belirttiği gibi, var olmayan bir anahtarı istisnasız sorgulayabilir ve anahtarı gruplamanın bir parçası olarak kullanabilirsiniz).

Hangisini kullandığınıza gelince, bu onları nasıl kullanmak istediğinize bağlıdır. Sürekli olarak değiştirilen birden çok değerin anahtar haritasını tutuyorsanız, a değiştirilebilir Dictionary<Key, List<Value>>olduğu için muhtemelen daha iyidir.

Bununla birlikte, bir veri diziniz varsa ve sadece anahtarla düzenlenmiş verilerin salt okunur bir görünümünü istiyorsanız, bir aramanın oluşturulması çok kolaydır ve size salt okunur bir anlık görüntü verecektir.


11

A ILookup<K,V>ve a arasındaki birincil fark Dictionary<K, List<V>>, bir sözlüğün değiştirilebilir olmasıdır; anahtar ekleyebilir veya kaldırabilir ve ayrıca aranan listeye öğe ekleyebilir veya listeden öğe kaldırabilirsiniz. Bir ILookupolan değişmez ve oluşturulan bir kez değiştirilemez.

Her iki mekanizmanın altında yatan uygulama aynı veya benzer olacaktır, bu nedenle arama hızları ve bellek ayak izi yaklaşık olarak aynı olacaktır.


1
@JohnBustos Performans açısından, hayır. Tamamen mantıklı. Yapının altından değiştiren bir başkası için endişelenmeyen bir yapıya referanslar iletebilirsiniz. Değişken olmamanın yapamayacağınız konusunda varsayımlar yapabilirsiniz.
Servy

Teşekkürler, Servy, sık sık ByRef değişkenleri geçirirken çok iyi bir nokta - En azından bu bir değiştirilemez emin olabilirsiniz. Teşekkürler!
John Bustos

2
@JohnBustos Bir yöntem parametresini geçirmenin varsayılan yönteminin değere göre olduğunu, açıkça byref eklemeniz gerektiğini ve bu çok nadiren yapılması gereken bir şey olduğunu unutmayın. Bu veri yapıları onları referans türleri yapan sınıflardır, bu nedenle değeri iletmek referansın değeridir, bu yüzden onu başka bir yönteme geçirmek arayanda görünür değişikliklere neden olabilir.
Servy

Teşekkürler, Servy, yaptığım şey için benim için yepyeni bir solucan kutusu açıyor :), ama ne dediğini anlıyorum. Teşekkürler!!
John Bustos

Kapakların altında Lookup'ın anahtar için hashbuckets kullanıp kullanmadığını biliyor musunuz?
paparazzo


4

İstisna bir seçenek olmadığında, Aramaya gidin

Bir yapı kadar verimli bir yapı elde etmeye çalışıyorsanız, Dictionaryancak girişte yinelenen bir anahtar olmadığından emin değilseniz Lookup, daha güvenlidir.

Başka bir cevapta belirtildiği gibi, null anahtarları da destekler ve rastgele verilerle sorgulandığında her zaman geçerli bir sonuç döndürür, bu nedenle bilinmeyen girdiye daha dirençli görünür (istisnaları yükseltmek için Sözlük'ten daha az eğilimli).

Ve özellikle System.Linq.Enumerable.ToDictionaryişlevle karşılaştırırsanız doğrudur :

// 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);

Alternatif, bir foreachdöngü içine kendi yinelenen anahtar yönetimi kodunu yazmak olacaktır .

Performans değerlendirmeleri, Sözlük: açık kazanan

Bir listeye ihtiyacınız yoksa ve çok sayıda öğeyi yönetecekseniz Dictionary(hatta kendi özel uyarlanmış yapınız) daha verimli olur:

        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);
        // ...

LookupHer anahtar için bir öğe listesi bulundurması gerektiği gibi , Sözlük'ten daha yavaştır (çok sayıda öğe için yaklaşık 3 kat daha yavaştır)

Arama hızı: Oluşturma: 00: 00: 01.5760444

Sözlük hızı: Oluşturma: 00: 00: 00.4418833

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.