2009-09-10 5 views
116

MSDN от объясняет Lookup, как это:Что такое Lookup <TKey, TElement>?

Lookup<TKey, TElement> напоминает Dictionary<TKey, TValue>. Разница заключается в том, что словарь < TKey, TValue > карты ключей к отдельным значениям, тогда как Уточняющий < TKey, TElement > карты ключей к коллекции значений.

Я не нашел это объяснение особенно полезным. Для чего используется Lookup?

ответ

172

Это крест между 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 для большинства из этих деклараций, в обычном коде)

+43

Думаю, чтобы этот ответ был лучше, вы могли бы заменить некоторые из варов. Для учебных целей я считаю, что легче следовать, когда типы выражаются четко. Просто мои 2 цента :) –

+3

Если у этого есть лучшее из обоих миров, то зачем беспокоиться о Словаре? –

+12

@KyleBaran: Потому что это было бы бессмысленно для подлинных коллекций ключей/значений, где есть только одно значение для каждого ключа. –

11

я успешно не использовал его раньше, но вот мое движение:

Lookup<TKey, TElement> будет вести себя в значительной степени как (реляционной) индекс базы данных на таблица без однозначного e ограничение. Используйте его в тех же местах, где вы использовали бы другой.

51

Один из способов подумать об этом: 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()); 
      Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); 
      Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); 
     } 
    } 
} 
+2

Может ли быть нулевой элемент в результатах поиска? Как бы вы это поняли? (Lookup является публично неизменным, насколько я могу судить, и я не думаю, что ToLookup будет эффективно изобретать ключи.) –

+8

Технически, да, поскольку Lookup возвращает пустую коллекцию для несуществующего ключа (я отредактировал свой пост, чтобы добавить образец кода, который показывает это). – bobbymcr

5

Я думаю, вы могли бы так утверждать: представьте, что вы создаете структуру данных для хранения содержимого телефонной книги. Вы хотите использовать ключ lastName, а затем firstName. Использование словаря здесь было бы опасно, потому что многие люди могут иметь одно и то же имя. Таким образом, словарь всегда будет, в лучшем случае, сопоставляться с одним значением.

Поиск будет отображать потенциально несколько значений.

Lookup ["Smith"] ["John"] будет представлять собой коллекцию размером один миллиард.

+0

Ваш ответ вдохновил мой последующий вопрос [«Как ToLookup() с несколькими индексами?»] (Http://stackoverflow.com/questions/15734454/how-tolookup-with-multiple-indexes). Как я могу воспроизвести такие, с несколькими индексами, поиск? Не могли бы вы ответить на него, используя любой другой образец или ссылку, где можно использовать 'Lookup [" Smith "] [" John "]'? – Fulproof

17

Одно использование Lookup может быть обратным Dictionary.

Предположим, у вас есть телефонная книга, реализованная как Dictionary с кучей (уникальных) имен в качестве ключей, каждое имя связано с номером телефона. Но два человека с разными именами могут иметь один и тот же номер телефона. Это не проблема для Dictionary, которая не заботится о том, чтобы две клавиши соответствовали одному значению.

Теперь вам нужен способ поиска, кому принадлежит данный номер телефона. Вы строите Lookup, добавляя все KeyValuePairs от Dictionary, но назад, со значением как ключом и ключом как значение. Теперь вы можете запросить номер телефона и получить список имен всех людей, у которых есть номер телефона.Построение Dictionary с теми же данными сбросят данные (или не в зависимости от того, как вы сделали это), так как делать

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

означает, что вторая запись перезаписывает первый - Док больше не будет отображаться.

Попытка написать одни и те же данные в несколько ином виде:

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

бы бросить исключение на второй линии, так как вы не можете Add ключ, который уже в Dictionary.

[Конечно, вы можете использовать некоторую другую единую структуру данных для поиска в обоих направлениях и т. Д. Этот пример означает, что вы должны регенерировать Lookup от Dictionary каждый раз, когда последний изменяется. Но для некоторых данных это может быть правильным решением.]

Смежные вопросы