开发者

LINQ Query - Selecting a key based upon the value having a property that matches a string?

开发者 https://www.devze.com 2023-03-13 06:06 出处:网络
I have an IDictionary I need to select the first Foo where the Bar.Prop1 matches a string value. public class Foo { }

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];
0

精彩评论

暂无评论...
验证码 换一张
取 消