Встречается необходимость, сгруппировав элементы, преобразовать их в структуру данных для поиска группы по ключу группировки. Это можно сделать, например, так:
1 | string[] names = {"Pavel", "Peter", "Andrew", "Anna", "Alice", "John"}; |
Ровно того же эффекта можно добиться и без цикла при помощи LINQ-метода ToDictionary
, имеющего следующую сигнатуру:
1 | IDictionary<K, V> ToDictionary(this IEnumerable<T> items, Func<T, K> keySelector, Func<T, V> valueSelector) |
Тогда предыдущий пример с foreach
в случае ToDictionary
примет следующий вид:
1 | string[] names = {"Pavel", "Peter", "Andrew", "Anna", "Alice", "John"}; |
Ещё проще воспользоваться LINQ-методом ToLookup
, имеющим следующие сигнатуры:
1 | ILookup<K, T> ToLookup(this IEnumerable<T> items, Func<T, K> keySelector) |
1 | ILookup<K, V> ToLookup(this IEnumerable<T> items, Func<T, K> keySelector, Func<T, V> valueSelector) |
В отличие от словаря, Lookup
является неизменяемым (immutable) типом. У него нет методов типа Add
и открытого конструктора. Интересно, что Lookup
по неизвестному ключу возвращает пустую коллекцию, а Dictionary в такой ситуации выбрасывает исключение. Также в Lookup
можно использовать ключи типа null
.
Замечу, что операции list.ToLookup(x => x)
и list.GroupBy(x => x).ToDictionary(group => group.Key)
семантически эквивалентны.
Пример с foreach
и ToDictionary
в случае ToLookup
примет следующий вид:
1 | string[] names = {"Pavel", "Peter", "Andrew", "Anna", "Alice", "John"}; |
В русскоязычной литературе Lookup
раньше именовался таблицей истинности. Lookup
можно использовать в построении обратного индекса. Обратный индекс — это структура данных, часто использующаяся в задачах полнотекстового поиска нужного документа в большой базе документов. По своей сути обратный индекс напоминает индекс в конце бумажных энциклопедий, где для каждого ключевого слова указан список страниц, где оно встречается.
Допустим наш документ определён так:
1 | public class Document |
Тогда для списка документов обратный индекс можно получить так:
1 | public static ILookup<string, int> BuildInvertedIndex(Document[] documents) |