2014-03-30 258 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. 經歷的項目,如果它們屬於當前組,添加計數器,否則你已經躍升到一個新的組,刷新計數器記錄值並重新啓動它