Какова точка поиска <TKey, TElement>?
MSDN объясняет поиск следующим образом:
A Lookup<TKey, TElement>
напоминает Dictionary<TKey,
TValue>
. Разница в том, что Словарь < TKey, TValue > сопоставляет ключи с одиночными значениями, тогда как Lookup < TKey, TElement > отображает ключи в коллекции значений.
Я не считаю это объяснение особенно полезным. Для чего используется Lookup?
Ответы
Ответ 1
Это крест между 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
для большинства этих объявлений в обычном коде.)
Ответ 2
Один из способов подумать об этом: 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());
}
}
}
Ответ 3
Одно использование Lookup
может заключаться в обратном преобразовании Dictionary
.
Предположим, что у вас есть телефонная книга, реализованная как Dictionary
с пучком (уникальными) именами в качестве ключей, каждое имя связано с номером телефона. Но два человека с разными именами могут иметь один и тот же номер телефона. Это не проблема для Dictionary
, которая не заботится о том, чтобы две клавиши соответствовали одному значению.
Теперь вам нужен способ поиска, кому принадлежит данный номер телефона. Вы создаете Lookup
, добавляя все KeyValuePairs
из вашего Dictionary
, но назад, со значением в качестве ключа и ключа в качестве значения. Теперь вы можете запросить номер телефона и получить список имен всех людей, у которых есть номер телефона. Построение a Dictionary
с теми же данными приведет к потере данных (или сбою, в зависимости от того, как вы это сделали), поскольку
dictionary["555-6593"] = "Dr. Emmett Brown";
dictionary["555-6593"] = "Marty McFly";
означает, что вторая запись перезаписывает первое - Doc больше не указан.
Попытка написать одни и те же данные несколько иначе:
dictionary.Add("555-6593", "Dr. Emmett Brown");
dictionary.Add("555-6593", "Marty McFly");
будет вызывать исключение во второй строке, так как вы не можете Add
ключ, который уже находится в Dictionary
.
[Конечно, вы можете использовать некоторую другую единую структуру данных для поиска в обоих направлениях и т.д. Этот пример означает, что вам нужно регенерировать Lookup
из Dictionary
каждый раз, когда последний изменяется. Но для некоторых данных это может быть правильным решением.]
Ответ 4
Я не использовал его раньше, но вот мой ход:
A Lookup<TKey, TElement>
будет вести себя как индекс (реляционной) базы данных в таблице без уникального ограничения. Используйте его в тех же местах, где вы использовали бы другой.
Ответ 5
Я думаю, вы могли бы так утверждать: представьте, что вы создаете структуру данных для хранения содержимого телефонной книги. Вы хотите использовать ключ lastName, а затем firstName. Использование словаря здесь было бы опасно, потому что многие люди могут иметь одно и то же имя. Таким образом, словарь всегда будет, в лучшем случае, сопоставляться с одним значением.
Поиск будет отображать потенциально несколько значений.
Поиск [ "Смит" ] [ "Джон" ] будет представлять собой коллекцию размером один миллиард.