Combining Where and OrderByDescending Using a Custom Method

Viewed 36

I'm trying to use a custom method for ordering but I also want to use that same custom method to only return results that match a certain value. I realize that the code below works but I was hoping there was a way to combine both methods to hopefully speed up the process.

public IEnumerable<List<decimal>> GetBestList(List<List<decimal>> inputList)
{
    var bestList = inputList.Where(x => x != null && CalculateAverage(x) > 0).
            OrderByDescending(x => CalculateAverage(x)));
            
    return bestList;
}

public decimal CalculateAverage(List<decimal> inputList)
{
    return inputList.Average();
}
2 Answers

As far as I understand you want to prevent recalculation of average, so you can use Select to create a temporary tuple containing average and original list, for example like that:

    public IEnumerable<List<decimal>> GetBestList(List<List<decimal>> inputList)
    {
        var bestList = inputList
            .Where(x => x != null )
            .Select(x => (x, Avg: CalculateAverage(x)))
            .Where(x => x.Avg > 0)
            .OrderByDescending(x => x.Avg)
            .Select(x => x.x);
        
        return bestList;
    }

The way to avoid performing the potentially expensive computation multiple times is to project the sequence into a new value that includes the list and the computation. This is simpler and easier with query syntax than method syntax:

public IEnumerable<List<decimal>> GetBestList(List<List<decimal>> inputList)
{
    var query = from list in inputList
                where list != null
                let average = CalculateAverage(list)
                where average > 0
                orderby average
                select list;
}
Related