Reputation: 2509
I have a dictionary of lists.
var dicAclWithCommonDsEffectivity = new Dictionary<string, List<int>>();
var list1 = new List<int>(){1,2,3};
var list2 = new List<int>(){2,4,6};
var list3 = new List<int>(){3,7,6};
var list4 = new List<int>(){8,7,6};
dicAclWithCommonDsEffectivity.Add("ab",list1);
dicAclWithCommonDsEffectivity.Add("bc",list2);
dicAclWithCommonDsEffectivity.Add("cd",list3);
dicAclWithCommonDsEffectivity.Add("de",list4);
I want to get the keys in dictionary for which atleast one matching value with the current key list.
for key "ab"(first list). I should get: "ab","bc" and "cd"
.Since these lists contain one of the matching element in {1,2,3}
Is there a way without looping through each item in the list of dictionary value.
Upvotes: 1
Views: 12013
Reputation: 30823
If what you mean is to visibly (not logically) remove the looping, you could use LINQ
with proper Where
filter to do that and Select
the keys
from the Dictionary
which have any value element(s) intersect(s) with the selected List
(List
in the Dictionary
with key == "ab"
) like this:
string key = "ab";
List<int> selectedList = dicAclWithCommonDsEffectivity[key];
var results = dicAclWithCommonDsEffectivity
.Where(x => x.Value.Any(y => selectedList.Contains(y)))
.Select(x => x.Key);
If you want to logically remove the looping too, please consider Mr. Skeet's answer.
Upvotes: 1
Reputation: 29036
It's always better to check for existence of the searchKey
in the Dictionary before accessing them. Then you can get the associated list in the dictionary for that particular key.
You can also try like this:
string searchKey = "ab";
if (dicAclWithCommonDsEffectivity.ContainsKey(searchKey))
{
var ListToSearch = dicAclWithCommonDsEffectivity[searchKey];
var resultKeys = dicAclWithCommonDsEffectivity.Where(x =>
x.Value.Any(y => ListToSearch.Contains(y)))
.Select(x => x.Key)
.ToList();
}
else
{
// Specified key was not found
}
Upvotes: 1
Reputation: 1503984
Is there a way without looping through each item in the list of dictionary value.
Something has to loop - dictionaries are only designed to look up by key, and you're not doing that other than for the first check.
You can do this fairly easily though:
private IEnumerable<string> GetMatchingKeys(
Dictionary<string, List<int>> dictionary, string key)
{
// TODO: Use TryGetValue if key might not be in dictionary
HashSet<int> elements = new HashSet<int>(dictionary[key]);
return dictionary.Where(pair => pair.Value.Any(x => elements.Contains(x)))
.Select(pair => pair.Key);
}
This uses the fact that Dictionary
implements IEnumerable<KeyValuePair<TKey, TValue>>
- so the Where
clause checks a particular entry by spotting if any of the elements of its value matches any of the elements of the original value. The Select
clause then projects the pair to just the key.
If you need to do this a lot and you're concerned about efficiency, another alternative would be to build a second dictionary from int
to List<string>
- basically a reverse mapping. You'd need to maintain that, but then you could easily fetch all the "original keys" mapping to each of the values corresponding to the given key, and just use Distinct
to avoid duplicates.
Upvotes: 7