Пример использования типа Lookup() в VB.NET
При хранении некоторых видов данных удобно использовать коллекции типа пара «ключ-значение» (тип KeyValuePair). В .NET для этого существует специальный тип Dictionary() – словарь, позволяющий хранить такие данные, добавлять и удалять данные в процессе выполнения программы, а также быстро и удобно извлекать их из словаря. Данные извлекаются по уникальному ключу. При попытке добавить значение с ключом, который уже существует в словаре, возникает исключение. Но что делать, если в реальных данных имеется ключ, которому соответствуют несколько разных значений? Для такого случая подойдёт тип Lookup(), работу с которым мы и рассмотрим далее.
Вот определение с сайта Microsoft:
Метод ToLookup(Of TSource, TKey)(IEnumerable(Of TSource), Func(Of TSource, TKey)) возвращает объект Lookup(Of TKey, TElement) – словарь, сопоставляющий ключи с коллекциями значений с помощью соответствия «один ко многим». Объект Lookup() следует отличать от словаря Dictionary(), который осуществляет взаимно однозначное сопоставление ключей с единственными значениями.
Для начала опишем данные, которые будем хранить в нашем словаре в виде структуры (или класса – как удобнее). Для примера пусть это будет некая абстрактная пара «код ошибки – информационное сообщение».
''' <summary> ''' Структура данных «код ошибки – информационное сообщение». ''' </summary> Private Structure myDataStructure Public code As Byte Public msg As String End Structure
Теперь создадим список, заполненный объектами типа нашей структуры:
Dim msgList As New List(Of myDataStructure) From { New myDataStructure With {.code = &H0, .msg = "Ошибок нет"}, New myDataStructure With {.code = &H1, .msg = "Недостаточно памяти"}, New myDataStructure With {.code = &H2, .msg = "Ошибка бита чётности"}, New myDataStructure With {.code = &H4, .msg = "Ошибка синхронизации"}, New myDataStructure With {.code = &H4, .msg = "Неверный адрес"} }
Теперь необходимо вызвать метод ToLookup() для нашего списка msgList(), и в параметрах метода задать, каким образом будет осуществляться преобразование. Присвоим результат переменной типа ILookup():
Dim codesMessages As ILookup(Of Byte, String) = msgList.ToLookup(Of Byte, String)(Function(p) p.code, Function(p) p.msg)
Теперь можно использовать наш словарь кодов и сообщений. Например, так:
''' <summary> ''' Выводит в консоль информационное сообщение по переданному коду. ''' </summary> Private Sub getMessageByCode(ByVal c as Byte) Dim sb As New StringBuilder For Each m As IEnumerable In codesMessages.Item(c) sb.AppendLine(m) Next Console.WriteLine(sb.ToString()) End Sub
Если передать в данную процедуру в качестве параметров коды 0, 1 или 2, соответствующие ключам объекта Lookup, то будут выведены соответствующие им информационные сообщения, а если передать в процедуру код "4", в консоль будет выведено два информационных сообщения.
Таким образом, когда требуется хранить значения и соответствующие им уникальные ключи – для этой цели подходит объект типа Dictionary, а когда одному ключу могут соответствовать несколько значений – хорошим решением может быть использование типа Lookup.