Complicated Linq filtering without nesting countless if/foreach

I have an collection with given fields:

class InternalConditionModel
    public string ProductId { get; set; }
    public double Value { get; set; }
    public DateTime DateFrom { get; set; }
    public DateTime DateThru { get; set; }
    public bool IsSSoldOnlyOnDisplay { get; set; }

And have to filter it based on given conditions:

If there is more than one item with the same ProductId within the collection, I check IsSoldOnlyOnDisplay and take the one that yields true. If however there are more than one true, I take item with the biggest Value.

Doing it via GroupBy(ProductId) and then doing multiple ifs/foreaches is pretty straight forward. But I wanted to know if there is a possibility to streamline it with linq into someting "prettier".

>Solution :

This should do it:

var result = items.GroupBy(x => x.ProductId).Select(x => x.OrderByDescending(y => y.Value).FirstOrDefault(y => x.Count(z => z.IsSSoldOnlyOnDisplay) == 1 ? y.IsSSoldOnlyOnDisplay : true));

First we group by the product id. Then we sort each group descending by the value (the item with the greatest value will be first). Of this sorted group, we take the first item. If the group has only one item with IsSSoldOnlyOnDisplay true, the condition of FirstOrDefault is IsSSoldOnlyOnDisplay, otherwise the condition is true, meaning it will just take the first item in the group. Because of the sorting which occured earlier, it will be the one with the highest value.

But think of yourself whether this code is really better than some loops and ifs. I don’t recommend forcing everything into a single LINQ query.


Leave a Reply