Multi-Keys Hash или Dictionary, список значений в качестве вывода
Я новичок в C# и мне нужно иметь общий список с несколькими ключами.
У меня есть три параметра, которые создают ключ моих данных. Для каждой записи (каждая три ключа) у меня есть набор значений.
Мне нужно иметь общий список, в котором значения каждого узла в списке будут значениями моих ключей и значением каждого узла, указывающего на список, который содержит связанные значения с этим ключом.
Ниже приведен пример моих данных и структуры данных, которые я ищу:
Key1 Key2 Key3 Value1 Value2 Value3
0 0 0 a b c
0 0 1 d e f
0 1 1 g h -
<0,0,0, List(a,b,c)> ---> <0,0,1,list(d,e,f)>---> <0,1,1,List(g,h)>--->Null
Я думал о том, чтобы иметь хеш-таблицу с несколькими ключами и значением, указывающим на объект, который является списком ссылок. Или создать словарь с этими тремя ключами и снова вернуть указатель на заголовок списка ссылок.
Буду признателен, если кто-нибудь подскажет, как мне это сделать в C#.
1 ответ
Во-первых, вы обязательно должны использовать Dictionary<TKey, TValue>
, и не HashTable
, Неуниверсальные типы коллекций действительно для обратной совместимости. Лучше использовать универсальные типы для нового кода.
Что касается вашей конкретной проблемы, вы заметите, что типы словаря.NET допускают только один ключ. Действительно, это типично для словарных коллекций вообще. Каждая запись в коллекции представляет собой одну пару ключ / значение.
Однако вы можете объединить три значения ключа в одно значение объекта и использовать его вместо ключа. И на самом деле.NET предоставляет различные Tuple
классы для достижения этой цели, разные классы для каждого количества параметров типа и, следовательно, для каждого количества элементов в объекте. Кроме того, все эти классы реализуют соответствующие сравнения и хеширование для использования в качестве словарного ключа.
Теперь, применяя это к вашему вопросу, у вас есть несколько вариантов, в зависимости от того, что вы действительно хотите сделать. К сожалению, не совсем понятно, что вы хотите сделать.:(
Если у вас когда-либо будет максимум три значения для каждого триплета ключевых значений, тогда я думаю, что предложение от комментатора Мефи в порядке. Вы можете объявить свою коллекцию и инициализировать ее примерно так:
Dictionary<Tuple<int, int, int>, Tuple<string, string, string>> collection =
new Dictionary<Tuple<int, int, int>, Tuple<string, string, string>>
{
{ Tuple.Create(0, 0, 0), Tuple.Create("a", "b", "c") },
{ Tuple.Create(0, 0, 1), Tuple.Create("d", "e", "f") },
{ Tuple.Create(0, 1, 1), Tuple.Create("g", "h", null) },
};
Обратите внимание, что null
используется для указания отсутствующего значения в кортеже значений словаря.
Однако, если вы буквально хотите использовать объект списка в качестве значения, вы можете вместо этого сделать что-то вроде этого:
Dictionary<Tuple<int, int, int>, List<string>> collection =
new Dictionary<Tuple<int, int, int>, List<string>>
{
{ Tuple.Create(0, 0, 0), new List<string> { "a", "b", "c"} },
{ Tuple.Create(0, 0, 0), new List<string> { "d", "e", "f"} },
{ Tuple.Create(0, 0, 0), new List<string> { "g", "h" } },
};
Что касается вышеупомянутого как списка пар ключ / значение, как и любой тип коллекции.NET, Dictionary<TKey, TValue>
может рассматриваться как перечисление значений, в данном случае посредством реализации IEnumerable<KeyValuePair<TKey, TValue>>
где TKey
а также TValue
те же типы, которые используются для самого объекта словаря. Так, например, вы можете сделать что-то вроде этого:
foreach (KeyValuePair<Tuple<int, int, int>, List<string>> kvp in collection)
{
// here, kvp.Key will have the Tuple<int, int, int> key value
// for the dictionary entry, while kvp.Value will have the
// List<string> value for the same entry.
}
Обратите внимание, что порядок перечисления типа словаря в.NET не определен. Вам не дают никаких гарантий, элементы будут возвращены в любом конкретном порядке, например, в том порядке, в котором они были добавлены. Если вам нужен конкретный заказ, вам придется как-то навязывать это себе.
Наконец, обратите внимание на приведенный выше пример KeyValuePair<TKey, TValue>
тип. На самом деле это просто особый случай кортежа (хотя он предшествует фактическому Tuple...
занятия в.NET). Т.е. это пользовательский класс, разработанный специально для хранения пар ключ / значение.
Вы можете, если хотите, самостоятельно объявить такой тип в качестве ключа для своего словаря. Это дает преимущество, заключающееся в том, что вы можете предоставить конкретное, читаемое имя для типа и, конечно, позволить вам избежать многословия, связанного с Tuple...
классы (Tuple.Create()
общие методы помогают, но объявления все еще могут быть громоздкими). Конечно, это происходит за счет написания собственного сравнения и хэш-кода.
Вы можете найти золотую середину, либо создав класс, который наследует Tuple...
вам нужен класс, в котором вы реализуете только конструктор (передавая параметры инициализации в базовый конструктор), например:
class CustomKey : Tuple<int, int, int>
{
public CustomKey(int i1, int i2, int i3) : base(i1, i2, i3) { }
}
или просто совмещая Tuple...
введите свой модуль с using
директива, дающая Tuple...
введите локально используемое имя, которое будет более читабельным, например:
using CustomKey = System.Tuple<int, int, int>;
Первый дает вам легкий доступ к читаемому имени в любом месте вашего проекта, но требует реализации (очень короткого) класса; последний требует меньше работы, но будет применяться только в одном исходном файле.