I'm improving on this answer with a couple of extension methods I've wrote. The first one is similar to how @Bronek wrote it, just a bit more concise. Simply put, if a key exists, it inserts into the already existing list (assuming it was initialized to begin with). Otherwise, it adds to the list.
public static void AddToList<K, V>(this Dictionary<K, List<V>> multiValueDictionary,
K key,
V value)
{
if (multiValueDictionary.TryGetValue(key, out List<V> lst))
lst.Add(value);
else
multiValueDictionary.Add(key, new List<V> { value });
}
This second function builds off the previous. In System.Linq, the extension method ToDictionary
which can transform any IEnumerable into a Dictionary. But what if you have the above scenario where you want to store multiple values for a single key? Well then the below extension will work!
public static Dictionary<K, List<V>> ToDictionaryValueList<T, K, V>(this IEnumerable<T> values, Func<T, K> keySelector, Func<T, V> elementSelector)
{
var tmp = new Dictionary<K, List<V>>();
foreach (var val in values)
tmp.AddToList(keySelector(val), elementSelector(val));
return tmp;
// NOTE: You can also use the below IEnumerable extensions to accomplish the same goal, but the above might be (?) more efficient, not sure
// return values
// .GroupBy(v => keySelector(v))
// .ToDictionary(v => v.Key, v => v.ToList());
}
With the above two, its now easy to transform any IEnumerable into one of these dictionaries.
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
List<Person> test = new List<Person>
{
new Person { Name = "Bob", Age = 22 },
new Person { Name = "Bob", Age = 28 },
new Person { Name = "Sally", Age = 22 },
new Person { Name = "Sally", Age = 22 },
new Person { Name = "Jill", Age = 22 },
}
// Aggregate each person
Dictionary<string, List<int>> results = test.ToDictionaryValueList((p) => p.Name, (p) => p.Age);
// Use the AddToList extension method to add more values as neeeded
results.AddToList("Jill", 23);
One thing to consider is that duplicate values aren't handled, as expected from a standard List
. You'll want to make extension methods for different collections like HashSet
if you need it.