如何在Linq中对对象查询进行排序和分组?

时间:2010-09-28 16:33:53

标签: .net vb.net linq-to-objects

如何在Linq查询中排序和分组?

我试过..

Dim iPerson = From lqPersons In objPersons Where Len(lqPersons.Person) > 0 Group lqPersons By key = lqPersons.Name Into Group Order By Group descending Select Group, key

    For Each i In iPerson
        tmp = tmp & vbNewLine & i.key & ", " & i.Group.Count
    Next

如果我删除了Order By Group Descending claus,上面的工作正常,但有了它,我在Next语句中收到错误。

  

至少有一个对象必须实现IComparable。

我的查询是获取我的类/对象中的人员列表,以及他们的名称被用作类/对象的项目的次数。

乔,4 | 詹姆斯,5 | 迈克,4岁

有没有人有任何想法我做错了什么?

5 个答案:

答案 0 :(得分:3)

您的查询没问题(在VB.NET中使用Group作为名称BTW没有问题......实际上您必须使用Group,所以不要担心),除非您应该使用Order By键。

P.S。测试

编辑:为了完整起见,您可以像这样重命名您的小组:

Dim iPerson = From lqPersons In objPersons
              Where Len(lqPersons.Person) > 0
              Group lqPersons By key = lqPersons.Name Into g = Group
              Order By key Descending
              Select g, key

然而,这与你的问题无关......只是澄清这一点。

答案 1 :(得分:2)

请原谅我的C#,但你不能做像...这样的事情。

objPersons.Where(p=> p.Person > 0).GroupBy(p => p.Name).Select(p => new { Name= p.Key, Number = p.Count()}).OrderByDescending(p=> p.Number);

主要想法:

  1. GroupBy就像你做的那样
  2. 使用您的密钥(名称)选择新对象并计算该组中的数量
  3. 按降序排序

答案 2 :(得分:2)

您在下一个语句中收到错误,因为执行For Each循环时执行查询(它被称为 defferd execution )。

该错误实际上表明您无法执行Ordey By Group,因为IGrouping未实现IComparable,因此Group By - 语句的结果不能由IGrouping本身订购。

您必须按IGrouping个对象的元素数排序。


试试这个(请注意,我不知道你的课程是怎样的......):

Dim objPersons = New YourClass() {New YourClass("Joe"), _
                                  New YourClass("Joe"), _
                                  New YourClass("Joe"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("Mike"), _
                                  New YourClass("Mike")}

Dim query = objPersons.Where(function(p) p.Person > 0) _
                      .GroupBy(Function(p) p.Name) _
                      .OrderByDescending(Function(g) g.Count) _
                      .Select(function(g) g.Key & ", " & g.Count())


For Each s In query
    Console.WriteLine(s)
Next

<强>输出:

James, 4
Joe, 3
Mike, 2

答案 3 :(得分:0)

是lqPersons.Name是一个字符串,还是包含first,last,middle等名称的结构或类?如果它是前者,你应该对此很好,因为字符串是IComparable。如果Name是某个用户定义类的对象,则需要在该类上实现IComparable(提供排序算法使用的CompareTo()方法),或者按Name的“原始”子属性排序,如LastName

编辑:刚看到别的东西。使用Group By时,结果的对象是Lookup;基本上是一个KeyValuePair,带有一组Values而不是一个。查找不是IComparable。因此,不要按组排序,而是尝试按该组的密钥标识符排序(lqPersons.Name)。

答案 4 :(得分:0)

我在VB中做过类似的事情。 I have it on my blog as well.但基本上这里是我开始使用的SQL。

SELECT orgno, psno, sche, projid, RecType, 
SUM(OBBudExpAmt) AS OBBudExpAmt, 
SUM(ABBudEncAmt) AS ABBudEncAmt
FROM tbl908_BudSPDGrps 
WHERE orgno = '210'
GROUP BY orgno, psno,  sche, projid, RecType

这是相应的LINQ。

Dim projids = From p In db.tbl908_BudSPDGrps _ 
Where p.orgno = options.GroupFilter  _
Group p By p.orgno, p.psno, p.sche, p.projid, p.RecType _
Into g = Sum(p.OBBudExpAmt), h = Sum(p.ABBudEncAmt) _
Order By orgno, psno, sche, projid, RecType _
Select sche, RecType, g, h

漂亮的自我解释。希望它可以帮到你。