Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ Min() and Max() optimisation

Tags:

c#

linq

I'm having some trouble doing it right.

I need to pick the minimum and maximum for a list inside a list inside a list

Any thought how I can create a optimized type?

var range = allFilteredCars
            .SelectMany(car => car.LeasingPlans
                .SelectMany(plan => plan.Durations)
                .Select(a => a.MonthlyPrice))
            .ToList();

        var min = range.Min();
        var max = range.Max();

The last Min() and Max() doesn't feel right.

Any thoughts?

like image 432
Roelant M Avatar asked Dec 24 '22 06:12

Roelant M


2 Answers

I can think of only one way to calculate min and max just by iterating one time on the entire collection which can be done using foreach loop

var min = Int32.MaxValue;
var max = Int32.MinValue;
foreach(var filteredCard in allFilteredCars)
{
    foreach(var leasingPlan in filteredCard.LeasingPlans) 
    {
        foreach(var car in leasingPlan.Durations) 
        {
          if(car.MonthlyPrice < min)
            min = car.MonthlyPrice;
          else if(car.MonthlyPrice > max)
            max = car.MonthlyPrice;
        }
     }
}

Assuming MonthlyPrice is of Int

like image 62
Ipsit Gaur Avatar answered Dec 25 '22 19:12

Ipsit Gaur


We will do a bad thing: a linq expression with a side effect.

int? min = null;
int? max = null;

allFilteredCars
    .SelectMany(car => car.LeasingPlans
        .SelectMany(plan => plan.Durations))
            .Select(a =>
            {
                if (min == null || a.MonthlyPrice < min.Value)
                {
                    min = a.MonthlyPrice;
                }

                if (max == null || a.MonthlyPrice > max.Value)
                {
                    max = a.MonthlyPrice;
                }

                return true;
            }).All(x => x);

In the end you don't really seem to need the range result... You only want the Min() and Max(), so we calculate it, and force the whole IEnumerable<> to be elaborated through the use of All().

You have to replace int? with the type of MonthlyPrice!

like image 43
xanatos Avatar answered Dec 25 '22 20:12

xanatos