Reputation: 768
I want to find the corresponding key when I have a list of objects as a value. Suppose I have a Dictionary,
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>();
I know I could do something like,
foreach (var item in dict)
{
foreach (var subItem in item.Value)
{
if (subItem.Equals(foo))
{
Console.WriteLine(item.Key);
}
}
}
But this takes a lot of time I have a huge data set. Is there a faster solution to this?
I know that the normal way of finding keys given the value, using LINQ is something like:
var keysWithMatchingValues = dict.Where(p => p.Value == myObject).Select(p => p.Key);
I am looking for a similar solution in my situation.
Upvotes: 2
Views: 1530
Reputation: 460288
LINQ isn't more performant most times, but it's often easier to write correct and readable code with LINQ. If no duplicate values are possible i'd use a HashSet<T>
instead of the list. If you know what type it is i'd use that type instead of object.
The LINQ version of your code would be....
with List.Contains
:
List<string> keysWithValue = dict
.Where(kv => kv.Value.Contains(foo))
.Select(kv => kv.Key);
.ToList();
or Enumerable.Any
:
List<string> keysWithValue = dict
.Where(kv => kv.Value.Any(v => foo.Equals(v)))
.Select(kv => kv.Key);
.ToList();
But as mentioned this wouldn't be more efficient. One way to improve performance would be to use a Lookup<TKey, TValue>
. If the dictionary doesn't change you only need to create it once:
var valueToKeyLookup = dict // make it an instance field, so that you don't have to create it always
.SelectMany(kv => kv.Value
.Distinct()
.Select(v => new {Key = kv.Key, Value = v})
)
.ToLookup(x => x.Value, x => x.Key);
Now the remaining code is very concise and efficient:
List<string> allKeysWithFoo = valueToKeyLookup[foo].ToList();
Note that this will even work if no list contains that value, then the result will be an empty list.
Upvotes: 3