Получить несколько значений по одному ключу в словаре

Есть некий словарь:

Dictionary<string, string> AuthorList = new Dictionary<string, string>();
AuthorList.Add("aaa", "гистидин");
AuthorList.Add("bbb", "фенилаланин");
AuthorList.Add("aaa", "кокаин");
AuthorList.Add("ccc", "глицин");
AuthorList.Add("ddd", "глицин");
AuthorList.Add("aaa", "атропин");

Как мне по ключу aaa получить все значения (в виде списка или массива)?


Ответы (3 шт):

Автор решения: EzikBro

Значения для каждого ключа хранятся в List, поэтому могут повторяться:

Dictionary<string, List<string>> AuthorDict = new Dictionary<string, List<string>>();

AuthorDict["aaa"] = new List<string>();
AuthorDict["bbb"] = new List<string>();
AuthorDict["ccc"] = new List<string>();

AuthorDict["aaa"].Add("1");
AuthorDict["bbb"].Add("2");
AuthorDict["aaa"].Add("3");
AuthorDict["ccc"].Add("4");
AuthorDict["bbb"].Add("2");

foreach (var item in AuthorDict)
    Console.WriteLine($"{item.Key}: {String.Join(", ", item.Value)}");

Вывод:

aaa: 1, 3
bbb: 2, 2
ccc: 4

Значения для каждого ключа хранятся в HashSet, поэтому будут уникальными:

Dictionary<string, HashSet<string>> AuthorDict = new Dictionary<string, HashSet<string>>();

AuthorDict["aaa"] = new HashSet<string>();
AuthorDict["bbb"] = new HashSet<string>();
AuthorDict["ccc"] = new HashSet<string>();

AuthorDict["aaa"].Add("1");
AuthorDict["bbb"].Add("2");
AuthorDict["aaa"].Add("3");
AuthorDict["ccc"].Add("4");
AuthorDict["bbb"].Add("2");

foreach (var item in AuthorDict)
    Console.WriteLine($"{item.Key}: {String.Join(", ", item.Value)}");

Вывод:

aaa: 1, 3
bbb: 2
ccc: 4
→ Ссылка
Автор решения: Максим Фисман

Почему не работает у вас

Так как ваш AuthorList имеет тип данных Dictionary<string, string>, то он состоит из пар KeyValuePair, где ключ - строка, и значение - строка. Таким образом, когда вы несколько раз записываете значения в ячейку с одним и тем же ключом, старое просто стирается (как в обычной переменной). Пример:

Dictionary<string, string> dict = new Dictionary<string, string>();
dict["Key1"] = "Value1";
Console.WriteLine(dict["Key1"]);
dict["Key1"] = "Value2";
Console.WriteLine(dict["Key1"]);
dict["Key1"] = "Value3";
Console.WriteLine(dict["Key1"]);

Вывод:

Value1
Value2
Value3

Что делать?

Если вы хотите хранить сразу несколько значений для каждого ключа, ваш выбор - List.

В таком случае словарь будет создаваться таким образом:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();

Конкретно вашу задачу можно реализовать следующим образом:

Dictionary<string, List<string>> AuthorDict = new Dictionary<string, List<string>>();

AuthorDict["aaa"] = new List<string>();
AuthorDict["bbb"] = new List<string>();
AuthorDict["ccc"] = new List<string>();

AuthorList["aaa"].Add("гистидин");
AuthorList["bbb"].Add("фенилаланин");
AuthorList["aaa"].Add("кокаин");
AuthorList["ccc"].Add("глицин");
AuthorList["ddd"].Add("глицин");
AuthorList["ddd"].Add("атропин");

В дальнейшем вы можете обращаться к списку значений или к определенному значению по ключу следующим образом:

AuthorList["bbb"]; // Список по ключу "bbb"
AuthorList["aaa"][1]; // Первый элемент из списка по ключу "aaa"

Дополнительно

В целом словарь представляет собой структуру KeyValuePair<TKey, TValue>, то есть и ключом, и значением может быть вообще любой тип данных. Поэтому в зависимости от ваших желаний и целей, вы можете использовать и очереди Queue, чтобы иметь возможности очередей, и хешсет HashSet, и даже другой словарь Dictionary. Например:

Dictionary<string, Queue<string>> QueuedDictionary = new Dictionary<string, Queue<string>>();
Dictionary<string, HashSet<string>> HashsetDictionary = new Dictionary<string, HashSet<string>>();
Dictionary<string, Dictionary<int, string>> DoubleDictionary = new Dictionary<string, Dictionary<int, string>>();

Все это можно назвать List'ами с дополнительными особенностями, но т.к. вы в своем вопросе их не упоминали, на этом эту тему я остановлю


P.S. Как мне по ключу aaa получить все значения (в виде списка или массива)? - с массивом реализовать это будет сложно, так как его длина не динамична, поэтому могут возникнуть сложности с инициализацией или чтением...

→ Ссылка
Автор решения: VladD

Вам нужен словарь, который по одному ключу может хранить несколько разных значений. Такие словари обычно называются как-то наподобие MultiDictionary.

К примеру, можно взять майкрософтовский MultiValueDictionary из nuget-пакета Microsoft.Experimental.Collections (осторожно, он пре-релизный!). Подключите пакет (вам придётся поставить галку Include prerelease), и ваш код станет просто таким:

MultiValueDictionary<string, string> AuthorList = new();
AuthorList.Add("aaa", "гистидин");
AuthorList.Add("bbb", "фенилаланин");
AuthorList.Add("aaa", "кокаин");
AuthorList.Add("ccc", "глицин");
AuthorList.Add("ddd", "глицин");
AuthorList.Add("aaa", "атропин");

var results = AuthorList["aaa"];
foreach (var result in results)
    Console.WriteLine(result);

На консоли

гистидин
кокаин
атропин

→ Ссылка