2015-10-15 105 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