Home > Blockchain >  Efficient way to get max for the individual properties using linq
Efficient way to get max for the individual properties using linq

Time:08-20

I have an IEnumerable list in which I want to get the highest value for a particular property from the list and then capture the same in the record and return the same.

Record :

public record EnvironmentOccupiedAndRelativeHumidityFields(
    double CoolingSetPointOccupied,
    double HeatingSetPointOccupied,
    double RelativeHumidityMax);

Code:

    public static EnvironmentOccupiedAndRelativeHumidityFields GetEnvironmentFields(IEnumerable<LibraryEnvironment> environments)
    {
        var occupiedAndHumidityFieldValues = environments
            .Select(l => new
            {
                coolingSetPointOccupied = l?.CoolingSetPointOccupied ?? 0D,
                heatingSetPointOccupied = l?.HeatingSetPointOccupied ?? 0D,
                relativeHumidityMax = l?.RelativeHumidityMax?? 0D
            }).ToList();
                                             
                                             

        return new(
            occupiedAndHumidityFieldValues.MaxBy(a => a.coolingSetPointOccupied),
            occupiedAndHumidityFieldValues.MaxBy(l => l.heatingSetPointOccupied),
            occupiedAndHumidityFieldValues.MaxBy(l => l.relativeHumidityMax)
        );
    }

I am trying to get the max of each field (coolingSetPointOccupied, heatingSetPointOccupied, relativeHumidityMax), which are nullable fields. If there is no value, I need to return the 0 but get an error in the return statement.

` cannot convert `Anonymous type is not assignable to parameter type double.`

Could anyone please let me know how to do the same?

CodePudding user response:

The current implementation will iterate the list 4 times:

  1. Creating the occupiedAndHumidityFieldValues variable.
  2. Calc max cooling
  3. Calc max heating
  4. Calc max humdity

The suggestion to simply loop over the collection once removes the multiple iterations. For a single loop, create a few variables to capture the max value and then compare/update for each loop.

For example:

int cooling = 0;
int heating = 0;
int humidity = 0;

foreach (LibraryEnvironment e in environments)
{
    if(e == null) continue;

    if(e.CoolingSetPointOccupied > cooling) {
        cooling = (int)e.CoolingSetPointOccupied;
    }

    if(e.HeatingSetPointOccupied > heating) {
        heating = (int)e.HeatingSetPointOccupied;
    }

    if(e.RelativeHumidityMax > humidity) {
        humidity = (int)e.RelativeHumidityMax;
    }

    // alternatively, use Math.Max
    cooling = Math.Max(cooling, e.CoolingSetPointOccupied ?? 0);
    heating = Math.Max(heating, e.HeatingSetPointOccupied ?? 0);
    humidity = Math.Max(humidity, e.RelativeHumidityMax ?? 0);
}

The above example is a single loop comparing the current value against the currently known max values. When the current value is greater than the known max value, it updates as-needed.

  • Related