HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Simple LINQ statement for report limit

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
linqsimplestatementlimitreportfor

Problem

What would be the most efficent way to calculate this?

var reportLimit = 96*1024;

IEnumerable memoryInUse = 
  things
    .Where(sample => sample.IsOn)
    .Select(sample => sample.MemoryInMb)
    .ToArray();

int totalUnderReportLimit = memoryInUse.Where(ram => ram  ram > memoryCalcFactor) * memoryCalcFactor;

return totalUnderReportLimit  + totalOverEqualReportLimit;

Solution

Well here's my take on it. If you want efficient in terms of speed, write a loop. LINQ is not for writing fast code, it's for writing concise code.

memoryInUse is just a collection of the memory counts of all the machines that are on. You then essentially partition those machines by some memoryCalcFactor to do some calculation.

The call to ToArray(), while somewhat helpful (you do the filter/projection once) isn't really needed. You can perform your calculation in one pass and therefore don't need it at all. Look at the following lines in your calculation:

var x = memoryInUse.Where(ram => ram  ram > memoryCalcFactor) * memoryCalcFactor;
return x + y;


What are we doing here?

  • Adding up all the sizes that are less than some factor



  • Counting all those that are greater than that factor multiplying by that factor.



  • Adding the previous results



Looking at this at a much higher level, what are we doing here? We're adding up the sizes limiting each size by some factor (a maximum). Write your code to do that.

This is how I'd write it:

var memorySizes = machines
    .Where(machine => machine.IsOn)
    .Select(machine => machine.MemoryInMB);
var result = memorySizes.Sum(size => Math.Max(size, memoryCalcFactor));


Otherwise if you don't want to take the performance hit LINQ will give you and use a loop, here's the equivalent:

var sum = 0;
foreach (var machine in machines)
{
    if (machine.IsOn)
    {
        sum += Math.Max(machine.MemoryInMB, memoryCalcFactor);
    }
}

Code Snippets

var x = memoryInUse.Where(ram => ram <= memoryCalcFactor).Sum();
var y = memoryInUse.Count(ram => ram > memoryCalcFactor) * memoryCalcFactor;
return x + y;
var memorySizes = machines
    .Where(machine => machine.IsOn)
    .Select(machine => machine.MemoryInMB);
var result = memorySizes.Sum(size => Math.Max(size, memoryCalcFactor));
var sum = 0;
foreach (var machine in machines)
{
    if (machine.IsOn)
    {
        sum += Math.Max(machine.MemoryInMB, memoryCalcFactor);
    }
}

Context

StackExchange Code Review Q#12911, answer score: 10

Revisions (0)

No revisions yet.