簡體   English   中英

LINQ-按類型分組

[英]LINQ - GroupBy Type

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

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> 我怎么做?

以我的經驗,匿名類型使您無法使用GroupBy 我要么創建一個新類,要么就不用花那么多精力,使用Tuple

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

那不是您現在使用的匿名類型:

new { i.ID, i.DepartmentID })

然后,在隨后的鏈接LINQ方法中的i將成為一個分組,而不是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);
}

該組中的每個分組都是一個項目列表。 您的.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)
    }
}

我添加了OrderBy和ThenBy調用,以幫助顯示如何使用分組鍵和分組中的項目。

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

進行分組后,您將擁有許多Item列表,因此,如果您也按thos字段對項目進行分組,則按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進行排序,盡管我會謹慎地保留順序

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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM