Партия времен я должен создать a Dictionary<KeyType, List<ValueType>>
Прежде чем я смогу начать использовать словарь, я должен сначала проверить, что Список был создан для того ключа.
//Can i remove these two lines?
if(!dict.ContainsKey(key))
dict[key]= new List<ValueType>;
//now use the key
dict[key].Add(value);
Я знаю его единственное "2 строки" кода, но он раздражает меня, и я думаю, что он может быть удален.
Я могу расширить словарь в некоторым образом, но прежде чем я сделаю это, я хочу знать, нашел ли кто-то умный способ удалить вышеупомянутое if
оператор.
В основном я хочу создать a Dictionary<KeyType, Collection<ValueType>>
и начните использовать его сразу же как dict[key].Add(value)
.
Вы можете создать что-то вроде Multimap из Google Java Collection ... или просто добавить такой метод расширения:
public static void AddValue<TKey, TValue>
(this IDictionary<TKey, List<TValue>> dictionary, TKey key, TValue value)
{
List<TValue> values;
if (!dictionary.TryGetValue(key, out values))
{
values = new List<TValue>();
dictionary.Add(key, values);
}
values.Add(value);
}
Как говорит Беван, Lookup
также может помочь, но вы можете создать его только с помощью метода ToLookup
, и вы не можете его изменить после этого. Во многих случаях это очень хорошо, но если вам нужна изменяемая карта, вам понадобится что-то вроде приведенного выше.
Чтобы добавить к ответам, вы также можете добавить более общее расширение, которое принимает делегат для инстанции:
public static TValue GetOrCreate<TKey, TValue>
(this IDictionary<TKey, TValue> dict,
TKey key,
Func<TKey, TValue> getValue)
{
TValue value;
if (!dict.TryGetValue(key, out value))
{
dict.Add(key, getValue(key));
}
return value;
}
, а затем вы можете предоставить любой метод создания реализации:
Dictionary<int, string> dict = new Dictionary<int, string>();
string result = dict.GetOrCreate(5, i => i.ToString());
Способ CONCURRENTDICTICE
метод удивительно полезен.
private ConcurrentDictionary<string, ICollection<int>> _dictionary;
private static ICollection<int> CreateEmptyList(string dummyKey)
{
return new List<int>();
}
private void AddValue(string key, int value)
{
ICollection<int> values = _dictionary.GetOrAdd(key, CreateEmptyList);
values.Add(value);
}
Iделиц
(C # 3): Обратите внимание, что
, как правило, не безопасно ни в потоке, поэтому, если вы хотите безопасность потоков с помощью этого метода расширения, вам придется вручную реализовать его так же, как и для других операций.
public static TValue GetOrAdd<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
Func<TKey, TValue> valueFactory)
{
TValue value;
if (!dictionary.TryGetValue(key, out value))
{
value = valueFactory(key);
dictionary.Add(key, value);
}
return value;
}
Взгляните на LookUp
класс, введенный с Linq в .NET 3.5 - это может быть именно то, что вы ищете: Словарь
, подобный классу, который поддерживает несколько элементов на ключ.
Возможно, единственным существенным недостатком является то, что все ваши элементы должны быть доступны в одном пакете, так как LookUp является неизменным.