patterncsharpMinor
Average value for each row
Viewed 0 times
eachaveragevalueforrow
Problem
I have these classes:
Each
This is a data sample:
To do this, I've written this code. Can I optimize that?
The final results look like this:
public class DelayReason
{
public virtual ICollection WorkOrders { get; set; }
}
public class WorkOrder
{
public virtual ICollection DelayReasons { get; set; }
//other fields
}Each
DelayReason has 0..* WorkOrders and it's the same for WorkOrders.This is a data sample:
To do this, I've written this code. Can I optimize that?
public void DelayReasonAverage()
{
List result = new List();
var reasons = _delayReasons.GroupBy(row => row, (k, t) => new
{
delayId = k.Id,
delayTitle = k.Title,
workOrders = k.WorkOrders,
count = t.Count()
}).OrderByDescending(row => row.count).ToList();
reasons.ForEach(row =>
{
var workOrders = row.workOrders.ToList();
ReportVM reportObj = new ReportVM() { DelayTitle= row.delayTitle };
for (int i = 0; i i)
reportObj.Count += workOrders[i].CreatedOn.DiffDays(workOrders[i + 1].CreatedOn);
}
reportObj.Count = reportObj.Count / row.count;
result.Add(reportObj);
});
}DiffDays extension Method:public static int DiffDays(this DateTime current,DateTime to)
{
return to.Subtract(current).Days;
}The final results look like this:
Solution
While the logic of this:
is valid. I think the for loop might not be necessary. You should be able to take the difference from the first to last:
In looking at the rest of that method it looks like the LINQ queries can be simplified quite a bit. Something like this should work:
I noticed your post has this method as void, but it's creating a list, so I changed the signature to reflect that. I also changed the way the average is calculated, by using Math.Round to get a more accurate reflection of the actual average.
for (int i = 0; i i)
reportObj.Count += workOrders[i].CreatedOn.DiffDays(workOrders[i + 1].CreatedOn);
}
reportObj.Count = reportObj.Count / row.count;is valid. I think the for loop might not be necessary. You should be able to take the difference from the first to last:
reportObj.Count = workOrders[0].CreatedOn.DiffDays(workOrders[workOrders.Count - 1].CreatedOn) / row.count;In looking at the rest of that method it looks like the LINQ queries can be simplified quite a bit. Something like this should work:
public List DelayReasonAverage()
{
return (from DelayReason dr in _delayReasons
let row = new
{
delayId = dr.Id,
delayTitle = dr.Title,
workOrders = dr.WorkOrders.ToList(),
count = _delayReasons.Count()
}
orderby row.count descending
let reportObj = new ReportVM()
{
DelayTitle = row.delayTitle,
Count = (int)Math.Round(row.workOrders[0].CreatedOn.DiffDays
(row.workOrders[row.workOrders.Count - 1].CreatedOn) / (double)row.count)
}
select reportObj).ToList();
}I noticed your post has this method as void, but it's creating a list, so I changed the signature to reflect that. I also changed the way the average is calculated, by using Math.Round to get a more accurate reflection of the actual average.
Code Snippets
for (int i = 0; i < workOrders.Count; i++)
{
if (workOrders.Count - 1 > i)
reportObj.Count += workOrders[i].CreatedOn.DiffDays(workOrders[i + 1].CreatedOn);
}
reportObj.Count = reportObj.Count / row.count;reportObj.Count = workOrders[0].CreatedOn.DiffDays(workOrders[workOrders.Count - 1].CreatedOn) / row.count;public List<ReportVM> DelayReasonAverage()
{
return (from DelayReason dr in _delayReasons
let row = new
{
delayId = dr.Id,
delayTitle = dr.Title,
workOrders = dr.WorkOrders.ToList(),
count = _delayReasons.Count()
}
orderby row.count descending
let reportObj = new ReportVM()
{
DelayTitle = row.delayTitle,
Count = (int)Math.Round(row.workOrders[0].CreatedOn.DiffDays
(row.workOrders[row.workOrders.Count - 1].CreatedOn) / (double)row.count)
}
select reportObj).ToList();
}Context
StackExchange Code Review Q#162102, answer score: 2
Revisions (0)
No revisions yet.