Lookup'ın anlamı nedir <TKey, TElement>?


155

MSDN, Lookup'ı şu şekilde açıklar:

Bir Lookup<TKey, TElement> bir benzer Dictionary<TKey, TValue>. Fark, bir Sözlük <TKey, TValue> anahtarları tek değerlerle eşlerken, Arama <TKey, TElement> anahtarları değer koleksiyonlarıyla eşleştirir.

Bu açıklamayı özellikle yararlı bulmuyorum. Arama ne için kullanılır?

Yanıtlar:


215

Bir IGroupingve sözlük arasında bir çarpıdır. Öğeleri bir anahtarla gruplandırmanıza izin verir, ancak daha sonra bu anahtarla verimli bir şekilde erişmenizi sağlar (yalnızca hepsini yinelemek yerine, GroupBybunu yapmanıza izin verir).

Örneğin, bir tür .NET türünü alıp ad alanına göre bir arama oluşturabilirsiniz ... daha sonra belirli bir ad alanındaki tüm türlere çok kolay bir şekilde ulaşabilirsiniz:

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

(Normalde varbu bildirimlerin çoğu için normal kodda kullanırdım.)


59
Bu cevabı daha iyi yapmak için bazı değişkenlerin yerini alabilirsin. Öğrenme amaçları için, türler açıkça ifade edildiğinde takip etmenin daha kolay olduğunu düşünüyorum. Sadece benim 2 sent :)
Alex Baranosky

3
Her iki dünyanın en iyisine sahipse, neden bir Sözlük ile uğraşasınız?
Kyle Baran

15
@KyleBaran: Çünkü anahtar başına yalnızca tek bir değerin olduğu orijinal anahtar / değer çifti koleksiyonları için anlamsız olurdu.
Jon Skeet

12
@KyleBaran Lookup<,>sadece Addsınırlı bir kullanımı olan değişmez bir koleksiyon ( örn. İçin bir yöntem olmadan ). Ayrıca, varolmayan bir tuşa bakarsanız, sadece özel bağlamlarda, örneğin linq ile anlamlı olan bir istisna yerine boş bir sıraya sahip olmanız anlamında genel amaçlı bir koleksiyon değildir. Bu, MS'in sınıf için bir kamu kurucusu sağlamadığı gerçeğiyle de uyumludur.
nawfal

Cevapları okumak jwg olduğunu -> bobbymcr -> jonskeet
snr

58

Bunu düşünmenin bir yolu şudur: Lookup<TKey, TElement>şuna benzer Dictionary<TKey, Collection<TElement>>. Temelde sıfır veya daha fazla elemanın listesi aynı tuşla döndürülebilir.

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
        }
    }
}

2
Arama sonucunda sıfır öğe olabilir mi? Bunu nasıl elde edersin? (Arama, anlatabildiğim kadarıyla halka açık şekilde değişmez ve ToLookup'un anahtarları etkili bir şekilde icat edeceğini sanmıyorum.)
Jon Skeet

8
Teknik olarak, evet, bir Arama mevcut olmayan bir anahtar için boş bir koleksiyon döndürdüğü için (bunu gösteren bir kod örneği eklemek için yazımı düzenledim).
bobbymcr

Cevapları okumak jwg olduğunu -> bobbymcr -> jonskeet
snr

Çok temiz ve yararlı bir cevap, keşke seçildi.
dakika

25

Bir kullanımı Lookupa'yı tersine çevirmek olabilir Dictionary.

DictionaryHer biri bir telefon numarasıyla ilişkilendirilmiş bir grup (benzersiz) ad olarak anahtar olarak uygulanmış bir telefon defteriniz olduğunu varsayalım . Ancak farklı adlara sahip iki kişi aynı telefon numarasını paylaşabilir. Bu, Dictionaryiki anahtarın aynı değere karşılık gelmesini umursamayan bir a için sorun değildir.

Şimdi belirli bir telefon numarasının kime ait olduğunu aramanın bir yolunu istiyorsunuz. Bir inşa Lookuptüm ekleyerek, KeyValuePairssizin gelen Dictionaryanahtar ve değer olarak anahtar olarak değerle, ama ters takmış. Artık bir telefon numarasını sorgulayabilir ve telefon numarası olan tüm kişilerin adlarının bir listesini alabilirsiniz. DictionaryAynı verilere sahip bir a oluşturmak veriyi düşürür (veya nasıl yaptığınıza bağlı olarak başarısız olur), çünkü

dictionary["555-6593"] = "Dr. Emmett Brown";
dictionary["555-6593"] = "Marty McFly";

ikinci girişin birincinin üzerine yazdığı anlamına gelir - Doküman artık listelenmiyor.

Aynı verileri biraz farklı bir şekilde yazmaya çalışın:

dictionary.Add("555-6593", "Dr. Emmett Brown");
dictionary.Add("555-6593", "Marty McFly");

Addzaten içinde bulunan bir anahtarı kullanamayacağınız için ikinci satıra bir istisna atarsınız Dictionary.

[Elbette, her iki yönde arama yapmak için başka bir tek veri yapısı kullanmak isteyebilirsiniz. Bu örnek Lookup, Dictionaryher değiştiğinde yeniden oluşturmanız gerektiği anlamına gelir . Ancak bazı veriler için doğru çözüm olabilir.]


Cevap, kavramı kavramak için çok önemlidir. +1. Cevapları okumak jwg olduğunu -> bobbymcr -> jonskeet
snr

15

Daha önce başarıyla kullanmadım, ama işte benim işim:

A Lookup<TKey, TElement>, benzersiz bir kısıtlama olmaksızın bir tablodaki (ilişkisel) veritabanı dizini gibi davranır. Diğerini kullandığınız yerlerde kullanın.


5

Sanırım şu şekilde tartışabilirsiniz: bir telefon rehberinin içeriğini tutmak için bir veri yapısı oluşturduğunuzu hayal edin. Önce lastName ve sonra firstName tuşlarıyla tuşlamak istiyorsunuz. Burada bir sözlük kullanmak tehlikeli olurdu çünkü birçok kişi aynı ada sahip olabilir. Yani bir Sözlük her zaman en fazla tek bir değerle eşleşir.

Bir Arama potansiyel olarak birkaç değere eşlenir.

Arama ["Smith"] ["John"] bir milyar büyüklüğünde bir koleksiyon olacak.


Cevabınız, "Birden çok dizin içeren ToLookup () nasıl?" . Birden çok dizin ile arama nasıl çoğaltabilirim? Kullanmanın mümkün olduğu yerlerde başka bir örnek veya referans kullanarak cevap verebilir misiniz Lookup["Smith"]["John"] ?
Fulproof
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.