Какой смысл в Lookup <TKey, TElement>? - PullRequest
       13

Какой смысл в Lookup <TKey, TElement>?

139 голосов
/ 10 сентября 2009

MSDN объясняет поиск следующим образом:

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

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

Ответы [ 5 ]

202 голосов
/ 10 сентября 2009

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

56 голосов
/ 10 сентября 2009

Один из способов думать об этом таков: 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
        }
    }
}
20 голосов
/ 08 июля 2013

Одно из применений 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 каждый раз, когда последний изменяется. Но для некоторых данных это может быть правильным решением.]

13 голосов
/ 10 сентября 2009

Я не успешно использовал его раньше, но вот мой путь:

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

5 голосов
/ 10 сентября 2009

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

Lookup отобразит потенциально несколько значений.

Lookup ["Smith"] ["John"] будет коллекцией размером один миллиард.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...