2015-10-15 148 views
1

我繼承了一些C#代碼。我不完全理解類型如何在LINQ的上下文中工作。我有一些看起來像這樣的代碼:LINQ - GroupBy類型

foreach (var item in Model.Items.GroupBy(i => i.ID)) 
{ DoStuff(item); } 

我試圖用更復雜的分組更新此代碼。我試圖通過IDDepartmentID進行分組。在試圖做到這一點,我有:

var items = Model.Items.GroupBy(x => new { i.ID, i.DepartmentID }).OrderBy(i => i.Name).ThenByDescending(i => i.OrderDate); 
foreach (var item in items) 
{ DoStuff(item); } 

當我編譯我的代碼,我得到的是說,一個編譯時錯誤:

Argument 1: cannot convert from 'System.Linq.IGrouping<<anonymous type:string ID, int DepartmentID>, MyProject.Item>' to 'System.Linq.IGrouping<MyProject.Item>' 

從這個錯誤,我可以告訴大家,我當我做了兩個分組時,基本上已經構建了一個新類型。但是,我無法弄清楚如何按照他們的IDDepartmentID對我的物品進行分組,然後僅返回System.Linq.IGrouping<MyProject.Item>。我怎麼做?

回答

0

您的分組是正確的,但是您的訂購導致了問題。

您已執行您的分組之後,你有Item所以訂購團體的許多列出了NameOrderDate只會意義,如果你用的公益領域分組的項目過於:

var items = Model.Items.GroupBy(x => new { 
          i.ID, 
          i.DepartmentID, 
          i.Name, 
          i.OrderDate }) 
         .OrderBy(i => i.Name) 
         .ThenByDescending(i => i.OrderDate); 

這聽起來像它可能正在改變功能,而不是你在做什麼。如果你想通過NameOrderDate然後進行排序的每個分組列表中,您既可以分組之前訂購Item S,雖然我會很謹慎的排序被保留

var itemGroups = Model.Items.OrderBy(i => i.Name) 
         .ThenByDescending(i => i.OrderDate) 
         .GroupBy(x => new { 
          i.ID, 
          i.DepartmentID, 
          i.Name, 
          i.OrderDate }); 

,或最好爲了每個列表時讀出來。

foreach(var itemGroup in itemGroups) 
{ 
    var orderedgroup = itemGroup.OrderBy(i => i.Name) 
           .ThenByDescending(i => i.OrderDate) 
} 
0

根據我的經驗,匿名類型無法與GroupBy無緣。我會創建一個新的類,它不值得那麼多的努力,用Tuple

new Tuple.Create(i.ID, i.DepartmentID) 

這就是你現在正在使用的匿名類型,而不是:

new { i.ID, i.DepartmentID }) 

然後在i隨後的鏈LINQ方法將是一個分組不是Items對象:

.OrderBy(i => i.Name) // this will not work 

i的在這種情況下將是一個IGrouping<Tuple<int, int>, Model.Items>;也就是說,它將是一個鍵值對。您必須在您循環訪問IGrouping對象時訂購。

var groupings = Model.Items.GroupBy(x => new Tuple<int, int>(i.ID, i.DepartmentID)); 
foreach (var group in groupings) 
{ 
    var groupKey = group.Key; 
    group = group.OrderBy(i => i.Name).ThenByDescending(i => i.OrderDate); 
    foreach (var groupedItem in group) 
     DoStuff(groupKey, groupedItem); 
} 
+0

我相信你可以縮短,如果你想從新元組(i.ID,i.DepartmentID)到Tuple.Create(i.ID,i.DepartmentID) –

+0

@AlexKrups好點 - 編輯。 – woz

0

該組中的每個分組都是一個項目列表。您的.OrderBy(i => i.Name)調用不起作用,因爲您要訂購的對象不是Model.Items對象,而是帶有鍵的Model.Items對象列表。這些鍵是您使用ID和DepartmentID屬性創建的匿名對象。

通常在分組中,您將有兩個嵌套循環,而不僅僅是一個。外層循環遍歷每個分組。內循環遍歷分組中的每個項目。你可以這樣做:

foreach(var grouping in Model.Items 
    .GroupBy(x => new { i.ID, i.DepartmentID }) 
    .OrderBy(b => b.Key.DepartmentID) 
    .ThenBy(t => t.Key.ID)) 
{ 
    Console.WriteLine("{0}, {1}", grouping.Key.DepartmentID, grouping.Key.ID); 
    foreach(var item in grouping.OrderBy(n => n.Name).ThenByDescending(i => i.OrderDate)) 
    { 
     Console.WriteLine("\t{0}", item.Name) 
    } 
} 

我增加了排序依據和ThenBy調用,方便您瞭解與兩個分組鍵和集團內部的項目是如何工作的。

+0

OP正在按'Name&OrderDate'排序。 –

+0

@RahulSingh編輯 – user2023861