2017-01-30 32 views
1

我想按列表進行分組,然後對每個組中的項目進行計數,然後根據計數選擇每個組的最大值。下面的代碼工作,並做我所需要的。問題在於它非常緩慢,特別是第二步。你知道一種以更有效的方式達到同樣結果的方法嗎? 然後按順序計數並選擇Max by group,性能問題

var grouppedList = sourceList.Where(j => j.field1 == "1000") 
    .GroupBy(i => new { mask = i.field2.Substring(0, 1), f3 = i.field3, f4 = i.field4 }) 
    .Select(k => new 
    { 
     f4 = k.Key.f4, 
     mask = k.Key.mask, 
     f3 = k.Key.f3, 
     Total = k.Count() 
    }); 

var totalsList = grouppedList 
    .Where(i => !grouppedList.Any(j => 
         j.mask == i.mask && j.f4 == i.f4 && j.Total > i.Total)) 
    .ToList(); 
+0

您是否嘗試在第一部分上創建列表,以便計數只能完成一次? –

+1

什麼_second_步驟?只有一個查詢,它在'ToList'處執行, –

+0

謝謝蒂姆!這正是問題所在。 – Manngo

回答

2

groupedList不是List。這是一個IEnumerable。所以每次訪問它時都會執行它。並且您對它的每個部分都進行訪問(在Where子句中)。我建議創建一個列表,從它(只執行一次查詢):

var grouppedList = sourceList.Where(j => j.field1 == "1000") 
    .GroupBy(i => new { mask = i.field2.Substring(0, 1), f3 = i.field3, f4 = i.field4 }) 
    .Select(k => new 
    { 
     f4 = k.Key.f4, 
     mask = k.Key.mask, 
     f3 = k.Key.f3, 
     Total = k.Count() 
    }).ToList(); 

另一種可能性是合併分組並獲得項目最總,我會做這樣的事情:

var grouppedList = sourceList.Where(j => j.field1 == "1000") 
.GroupBy(i => new { mask = i.field2.Substring(0, 1), f3 = i.field3, f4 = i.field4 }) 
.Select(k => new 
{ 
    f4 = k.Key.f4, 
    mask = k.Key.mask, 
    f3 = k.Key.f3, 
    Total = k.Count() 
}) 
.GroupBy(x => new {x.mask, x.f4}) 
.Select(x=>x.OrderBydescending(t=>t.Total).First()); 
.ToList(); 
+0

@Manngo如果它幫助你,我會感謝一個upvote :) –

+0

我肯定會使用第二種方法(或類似的)+1 –

1

此代碼看起來很慢的原因可能是您重複grouppedList兩次的事實。

var totalsList = grouppedList.Where(i => !grouppedList.Any(
    j => j.mask == i.mask && j.f4 == i.f4 && j.Total > i.Total) 
).ToList(); 

將迭代groppedList在內Where語句來爲groppuedList所有元素。您可以考慮強制立即執行與ToList爲eample:

var grouppedList = sourceList.Where(j => j.field1 == "1000") 
.GroupBy(i => new { mask = i.field2.Substring(0, 1), f3 = i.field3, f4 = i.field4 }) 
.Select(k => new 
{ 
    f4 = k.Key.f4, 
    mask = k.Key.mask, 
    f3 = k.Key.f3, 
    Total = k.Count() 
}).Tolist(); // this forces an immediate execution of your select-statement 

現在當你打電話給你的第二個語句

var totalsList = grouppedList.Where(i => !grouppedList.Any(j => j.mask == i.mask && j.f4 == i.f4 && j.Total > i.Total)).ToList(); 

它會使用媒體鏈接物化,而不是一次又一次地執行查詢列表。