Reputation: 1571
I have what can potentially be a very large list of Dictionary objects that I will need to find a particular value from a key. I can certainly do something like
foreach(Dictionary<long, string> t in Foo)
{
if (t.TryGetValue(key, out name))
break;
}
and this will happily iterate through Foo until it finds the key or the foreach ends.
To speed this up, I'd prefer to use a small amount of LINQ. If this was a normal list, I'd be ok, but as this is a List of Dictionary objects, I'm not too sure how it's done.
Help or advice appreciated.
Upvotes: 6
Views: 14273
Reputation: 16324
I think you have written the most efficient version of what you want to do. Since Linq doesn't play nicely with output parameters, it will take slightly longer. But here is how you would do it:
var dict = Foo.FirstOrDefault(d => d.ContainsKey(key));
if (dict != null) { dict.TryGetValue(key, out name); }
Upvotes: 6
Reputation: 1839
You have the key setup as a long type.
long key = 1;
Dictionary<long, string> name = foo.Where(d => d.ContainsKey(key)).First();
Upvotes: -1
Reputation: 10325
Well, depending on the amount of dictionaries in Foo
there might be an advantage in using Parallel LINQ (PLINQ) instead:
string name = null;
Parallel.ForEach(foo, f =>
{
if (name != null)
return;
if (f.ContainsKey(key))
name = f[key];
});
The implementation assumes that the given key maps to the same value OR that the key is unique across all dictionaries. Also it is assumed that the value is not null.
With 5,000,000 dictionaries containing one key and one value this runs about 150 ms faster than your original implementation.
Benchmarks (2.4GHz Intel Core i5 with two physical cores and two virtual cores):
However, I want to stress that PLINQ is not necessarily always the answer to getting things run faster. In some cases where you have code that uses parallel foreach loops to traverse few elements, the actual cost of starting the threads in the background is actually much much more expensive than just iterating using a simple for loop - so, use it when there are many elements to iterate through :)
Upvotes: 0
Reputation: 156524
This code will be shorter, but will take just a tiny bit longer:
var dictWithKey = Foo.First(d => d.ContainsKey(key));
name = dictWithKey[key];
The real question, though, is why you're using a list of dictionaries for this, especially since you say you want "to speed this up." That tells me it's probably something your code will do more than once, right?
A more appropriate approach would probably be to keep a single dictionary that contains all of the key/value pairs, so you can do a single lookup rather than iterating through multiple dictionaries.
Upvotes: 3