Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting specific elements from IGrouping using LINQ

Tags:

c#

linq

public class Item
{
    public int Id {get; set;}
    public bool Selected {get; set;}
}

List<Item> itemList = new List<Item>(){ /* fill with items */ };

I need to create a list of Items that meet the following criteria. From itemList, I need to group the items by Id and then choose a single item from each group. The chosen item must be one in which Selected == true. If no item in the group is selected, then any item can be chosen, it doesn't matter, but one must be chosen.

Based on this question: How to get distinct instance from a list by Lambda or LINQ

I was able to put together the following, which seems to work:

var distinctList = itemList.GroupBy(x => x.Id, 
    (key, group) => group.Any(x => x.Selected) ? 
        group.First(x => x.Selected) : group.First());

Is there a more efficient or simpler way to achieve this? I tried FirstOrDefault() but couldn't seem to make it do what I needed. My concern with the efficiency in the above code, is the call to Any().

like image 477
J. Andrew Laughlin Avatar asked Feb 18 '26 22:02

J. Andrew Laughlin


1 Answers

You can indeed use the FirstOrDefault extension method, but use the version that takes a predicate, and combine it with the coalesce operator (??) like so (I've used query syntax here to make it easier):

var distinctList =
    from item in itemList
    group item by item.Id into g
    select g.FirstOrDefault(i => i.Selected) ?? g.First();

Using the predicate in FirstOrDefault, you are picking the first item where the Selected property is true. If there is none, then assuming your type is a reference type (and this is important this to work with FirstOrDefault), it will return null.

If null is returned, then you'll just return the first item in the group (through the call to First), since any item can be returned and a group can't exist without items in it (so the call to First is always guaranteed to succeed).

Basically, you are applying a selector to the result of the grouping, not while grouping.

like image 160
casperOne Avatar answered Feb 21 '26 11:02

casperOne



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!