Filtering a Dictionary by value with a List as the value
Filtering out entries in a dictionary is not too difficult when the key and value are simple. For example if you had -
IDictionary oneToFourDictionary = new Dictionary {{ "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } };
You could easily filter out all values greater than 2.
IDictionary onlyGreaterThanTwoDictionary = oneToFourDictionary.Where(pair => pair.Value > 2).ToDictionary(pair => pair.Key, pair => pair.Value);
But it gets a little more complex when you have a dictionary where the value is an IList
any you want to filter out certain entries in the list. But fortunately this is not too difficult either when using the ConcurrentDictionary
.
In the example below I am using a string as the key and list of ints as the value. Of course the same principle applies if your key and value are different.
I’m using a List as my filter, i.e. only numbers in this list are considered valid. Entries in the dictionary should be removed if the values are not in this list.
1using System.Collections.Concurrent;
2using System.Collections.Generic;
3using System.Linq;
4
5namespace ConcurrentDictionaryWithList
6{
7 class Program
8 {
9 static void Main(string[] args)
10 {
11 Program p = new Program();
12
13 IDictionary<string, IList<int>> unfilteredDictionary = p.PopulateUnfilteredDictionary();
14
15 IList<int> filter = new List<int> {5, 1, 2};
16
17 IDictionary<string, IList<int>> filteredDictionary = p.Filter(filter, unfilteredDictionary);
18 }
19
20 private IDictionary<string, IList<int>> Filter(IList<int> filter, IDictionary<string, IList<int>> unfilteredDictionary )
21 {
22 ConcurrentDictionary<string, IList<int>> filteredResults = new ConcurrentDictionary<string, IList<int>>();
23
24 foreach (KeyValuePair<string, IList<int>> unfilteredEntry in unfilteredDictionary)
25 {
26 foreach (int number in unfilteredEntry.Value)
27 {
28 if (filter.Contains(number))
29 {
30 filteredResults.AddOrUpdate(unfilteredEntry.Key, new List<int> { number }, (key, value) => { value.Add(number);
31 return value;
32 });
33 }
34 }
35 }
36 return filteredResults;
37 }
38
39 private IDictionary<string, IList<int>> PopulateUnfilteredDictionary()
40 {
41 IDictionary<string, IList<int>> unfilteredDictionary = new Dictionary<string, IList<int>>();
42 unfilteredDictionary.Add("key1", new List<int> { 1, 2, 3, 4, 5 });
43 unfilteredDictionary.Add("key2", new List<int> { 1, 7, 8, 9, 10 });
44 unfilteredDictionary.Add("key3", new List<int> { 5, 10, 15 });
45 unfilteredDictionary.Add("key4", new List<int> { 200, 300, 400 });
46
47 return unfilteredDictionary;
48 }
49
50 // Showing the simple filter just for completeness.
51 private void SimpleDictionaryFilter()
52 {
53 IDictionary<string, int> oneToFourDictionary = new Dictionary<string, int> {{ "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } };
54
55 IDictionary<string, int> onlyGreaterThanTwoDictionary = oneToFourDictionary.Where(pair => pair.Value > 2)
56 .ToDictionary(pair => pair.Key, pair => pair.Value);
57
58 }
59 }
60}