patterncsharpModerate
Simple LINQ statement for report limit
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.
The call to
What are we doing here?
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:
Otherwise if you don't want to take the performance hit LINQ will give you and use a loop, here's the equivalent:
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.