Automatically create a collection in the <Key, Collection <Value>> dictionary

Many times I need to create a Dictionary<KeyType, List<ValueType>>

Before I start using the dictionary, I must first verify that the List was created for this key.

 //Can i remove these two lines? if(!dict.ContainsKey(key)) dict[key]= new List<ValueType>; //now use the key dict[key].Add(value); 

I only know its "2 lines" of code, but it annoys me, and I think it can be deleted.

I can expand the dictionary, but before I do this, I want to know if anyone has found a smart way to remove the above if .

Basically, I want to create a Dictionary<KeyType, Collection<ValueType>> and start using it right away, like dict[key].Add(value) .

+7
collections dictionary c #
source share
4 answers

You can create something like the Google Java Collection Multimap ... or just add an extension method as follows:

 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); } 

As Bevan says, Lookup can help, but you can only create it using the ToLookup method, and you can change it after that. In many cases, this is good, but if you need a changeable card, you will get something like the above.

+6
source share

Look at the LookUp class introduced with Linq in .NET 3.5 - this may be exactly what you are looking for: a Dictionary as a class that supports multiple key elements.

Perhaps the only significant drawback is that you should have all of your elements in one batch, since LookUp is immutable.

+2
source share

The ConcurrentDictionary<T,K>.GetOrAdd amazingly useful.

 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); } 

Edit: Here is an example of implementing a function as an extension method for IDictionary<T,K> (C # 3):

Please note that IDictionary<TKey, TValue> is generally not thread safe, so if you need thread safety using this extension method, you will have to manually implement it the same way as for other operations.

 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; } 
+2
source share

To add answers, you can also add a more general extension that the delegate accepts to instantiate:

 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; } 

and then you can provide any way to create an instance that you like:

 Dictionary<int, string> dict = new Dictionary<int, string>(); string result = dict.GetOrCreate(5, i => i.ToString()); 
+1
source share

All Articles