如何在 Linq to 对象查询中排序依据和分组依据?

发布于 2024-09-24 23:13:20 字数 626 浏览 1 评论 0原文

如何在 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子句,上面的方法就可以工作,但是有了它,我在Next语句上收到错误。

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

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

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

有谁知道我做错了什么吗?

How do I order by and group by in a Linq query?

I tried..

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

The above works if I remove the Order By Group Descending claus, but with it, I get an error on the Next statement..

At least one object must implement IComparable.

My query is to obtain a list of the people in my class/object with how many times their name is used as an item of the class/object.

I.e.

Joe, 4 |
James, 5 |
Mike, 4

Does anyone have any ideas what I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

诗笺 2024-10-01 23:13:20

你的查询没问题(顺便说一句,在 VB.NET 中使用 Group 作为名称没有问题......实际上你必须使用 Group,所以不用担心),除了你应该有 Order By 键。

ps 已测试。

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

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

但这与您的问题无关......只是澄清这一点。

Your query is fine (there's no problem with using Group in VB.NET as a name BTW ... actually you MUST use Group, so don't worry about that), except you should have Order By key.

p.s. Tested.

EDIT: For completeness, you can rename your Group like so:

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

However that has nothing to do with your problem ... just clarifying that point.

痴者 2024-10-01 23:13:20

请原谅我的 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. 像你一样
  2. 进行 GroupBy 使用你的键(名称)选择一个新对象并计算该组中有多少个
  3. 按降序排序

Excuse my C#, but couldn't you do something like...

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

Main Idea:

  1. GroupBy as you did
  2. Select into a new object using your Key (Name) and counting how many in that group
  3. Order by descending
擦肩而过的背影 2024-10-01 23:13:20

您会在下一条语句中收到错误,因为在执行 For Each 循环时执行查询(称为延迟执行)。

该错误实际上表明您无法执行 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

You get the error on the next statement because the query is executed when the For Each loop is executes (it's called defferd execution).

The error actually says that you can't do Ordey By Group because IGrouping doesn't implement IComparable, so the result of your Group By-statement can't be ordered by the IGrouping itself.

You have to order by the number of elements of the IGrouping objects.


Try this (note that I don't know how your classes look like...):

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

Output:

James, 4
Joe, 3
Mike, 2
当梦初醒 2024-10-01 23:13:20

lqPersons.Name 是一个字符串,还是一个包含名字、姓氏、中间名等的结构或类?如果是前者,你应该擅长这个,因为字符串是 IComparable 的。如果 Name 是某个用户定义类的对象,则需要在该类上实现 IComparable(提供排序算法使用的 CompareTo() 方法),或者按 Name 的“原始”子属性(例如 LastName)实现 Order By 。

编辑:刚刚看到其他东西。当您使用 Group By 时,生成的对象是 Lookup;基本上是一个包含一组值而不是一个值的 KeyValuePair。查找不是 IComparable。因此,不要按组排序,而是尝试按该组的键标识符 (lqPersons.Name) 排序。

is lqPersons.Name a string, or a struct or class containing first, last, middle, etc names? If it's the former, you should be good with this as strings are IComparable. If Name is an object of some user-defined class, you will either need to implement IComparable on that class (providing a CompareTo() method used by sorting algorithms), or Order By a "primitive" sub-property of Name, like LastName.

EDIT: Just saw something else. When you use Group By, the object that results is a Lookup; basically a KeyValuePair with a collection of Values instead of just one. Lookups are not IComparable. So instead of ordering by the Group, try ordering by the key identifier for that Group (lqPersons.Name).

国产ˉ祖宗 2024-10-01 23:13:20

我在VB中也做过类似的事情。 我的博客上也有它。 但基本上这是我开始使用的 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

非常不言自明。希望对您有帮助。

I've done something similar in VB. I have it on my blog as well. But basically here is the SQL I started with.

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

And here is the corresponding 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

Pretty self-explanitory. Hope it helps you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文