2014-03-30 34 views
0

我有一个大的15分钟值的大名单,我想将它们汇总到几个小时。我这样做非常简单的方法:总价值需要很长时间

for (; from <= to; from = from.AddHours(1)) 
{ 
    List<DataPoint> valuesToAgregate = data.Where(x => x.TimeStamp >= from && x.TimeStamp < from.AddHours(1)).ToList(); 
    dailyInputData.Add(valuesToAgregate.Sum(x=>x.Val)); 

} 

这样,它需要大量的时间,像值的35K 30秒有没有什么办法来优化呢?也许使用排序功能或一些如何添加索引列表或使用分组而不是for循环?

+0

你真的需要临时'List '实例吗? –

+0

它有很大的不同吗?这是简化逻辑,我将这个列表传递给其他方法。但问题是data.Where(x => x.TimeStamp> = from && x.TimeStamp kosnkov

+0

@kosnkov这使得区别,你正在每个循环中创建一个数组。不仅如此,你正在循环两次序列(一个用'ToList'另一个用'Sum') –

回答

2

当然,如果您以前通过TimeStamp预订您的清单,这将更快。例如:

var orderedData = data.OrderBy(item => item.TimeStamp).ToList(); 
int firstIndex = 0; 
var from = orderedData.First().TimeStamp; 
var to = orderedData.Last().TimeStamp; 
while (from < to) 
{ 
    var sum = 0; 
    var newTo = from.AddHours(1); 
    while (firstIndex < data.Count && orderedData[firstIndex].TimeStamp < newTo) 
    { 
     sum += orderedData[firstIndex].Val; 
     ++firstIndex; 
    } 
    dailyInputData.Add(sum); 
    from = from.AddHours(1); 
} 
+0

而不是使用'.Count()'方法你可以使用'List '的'Count'属性,当数据类型为'List '或'IList ' –

+0

@ Selman22时,可以使用'Count'属性,是的,你说得对,thanx。不是'IList ',我们可以使用'orderedData'并获得'Count'。 – idlerboris

1
data = data.Sort(x=>x.TimeStamp); 
int counter = 0; 
var boundary = from.AddHours(1); 
foreach(var d in data){ 
    if(d.TimeStamp > boundary){ 
     boundary = boundary.AddHours(1); 
     counter = 0; 
     dailyInputData.Add(counter); 
    } 
    ++counter; 
} 

这个问题的关键在于逻辑

  1. 列表中从开始扫描到结束的每找到候选值(你的where子句)
  2. 候选值时间插入到另一个临时列表
  3. 临时列表是THEN从头到尾扫描以计算总和

最快的方法:

  1. 排序列表
  2. 经历的项目,如果它们属于当前组,添加计数器,否则你已经跃升到一个新的组,刷新计数器记录值并重新启动它