LINQ Query - Selecting a key based upon the value having a property that matches a string?
I have an IDictionary
I need to select the first Foo where the Bar.Prop1 matches a string value.
public class Foo { }
public class Bar
{
public String Prop1 { get; set; }
}
right now I have it like so...
foreach (var kvp in MyDictionary)
{
if (kvp.Value.Prop1 == theString)
{
var key = kvp.Key;
//Do something with it
break;
}
}
But that just doesn't seem as clean as a LINQ Query is. ReSharper turned it into:
foreach (var kvp in MyDictionary.Where(kvp => kvp.Value.Prop1 == theString))
{
var key = kvp.Key;
//Do something with it
//break; is unnecessary because I only开发者_JAVA百科 get one kvp back anyways.
}
I only want the very first item that matches, because I don't ever expect to get back more than one KVP. That goes against the business logic, so Unit Testing takes care of that.
I only want the very first item that matches, because I don't ever expect to get back more than one KVP. That goes against the business logic, so Unit Testing takes care of that.
If this is the case, I would argue you need to use a stronger code guarantee of your intention, and that would be the Single
(or SingleOrDefault
) method. First
is going to return the first object of arbitrarily many that match a given predicate. If many goes against your expectations and business rules, this seems to be an error. Treat it as such.
var key = MyDictionary.Single(pair => pair.Value.Prop1 == someValue).Key;
With Single
, if there is more than one matching item in a sequence, it will result in an exception.
SingleOrDefault
allows for 0 or 1, but never more. If using this approach, you'd want to capture the result and compare to null before performing additional operations with it (firing methods, accessing properties, etc.).
var key = MyDictionary.First(kvp => kvp.Value.Prop1 == theString).Key;
@Bala R's answer is correct, but Anthony Pegram makes a very good point in his comment on the OP. If you're doing this more than a few times with different keys, what you should do instead is reverse the dictionary, so you don't have to traverse the entire collection every time you want a value.
// Do this just once: it's expensive
var reverseDict = MyDictionary.ToDictionary(kvp => kvp.Value.Prop1, kvp => kvp.Key);
...
// Do this as many times as you need: it's cheap
var key = reverseDict[someValue];
精彩评论