LINQ到对象 - 这个简单的复合键分组有什么问题?

时间:2011-05-04 16:22:19

标签: linq-to-objects

好的...第一次在这里发帖提问。我正在尝试演示LINQ的几个功能并且遇到了障碍。以下查询未按预期执行:

Dim peopleByAgeAndName = _
    From p In (New PeopleRepository).GetAll
    Group By key = New With {p.Age, p.Name} Into Group
    Select Group

以下是非常简单的PeopleRepository:

Public Class PeopleRepository
     Public Function GetAll() As List(Of Person)
        Dim people As New List(Of Person)
        people.Add(New Person With {.Name = "Test Name #1", .Age = 33})
        people.Add(New Person With {.Name = "Test Name #1", .Age = 33})
        people.Add(New Person With {.Name = "Test Name #2", .Age = 0})
        people.Add(New Person With {.Name = "Test Name #3", .Age = 0})
        people.Add(New Person With {.Name = "Test Name #4", .Age = 0})
        people.Add(New Person With {.Name = "Test Name #5", .Age = 35})
        people.Add(New Person With {.Name = "Test Name #1", .Age = 39})
        Return people
    End Function
End Class

这是更简单的Person类:

Public Class Person
    Property Name As String
    Property Age As Integer
End Class

显然,这是用于测试目的的所有代码设置。执行peopleByAgeAndName查询后,我希望得到6组。每个包含一个Person对象,除了对应于“Test Name#1”的组和33岁。不管我做什么,我都得到7组,每组一个元素。

有什么想法?我想知道LINQ到对象是否正常?再次,它是所有测试代码。我只是想更好地理解这是如何工作的。我的理解是,当使用匿名对象作为键时,它应该对组进行逐个属性的比较。我应该得到6组,而不是7.

谢谢!

更新 -

对于记录,在C#中重写的查询完全按照我的预期执行:

 var peopleByAgeAndName =
        from p in peopleRepository.GetAll()
        group p by new {p.Age, p.Name}  into g 
        select g;

我得到6组而不是7组。我还确认组密钥在VB中不可用但在C#中。有点奇怪。

3 个答案:

答案 0 :(得分:1)

我为我的设计情况找到了解决方案...在Visual Basic中,您必须将“Key”属性添加到匿名类型中可用于确定唯一性的任何属性:

Dim peopleByAgeAndName = _
    From p In (New PeopleRepository).GetAll
    Group p By k = New With {Key p.Age, Key p.Name} Into g = Group
    Select g

现在就像魅力一样!谢谢你的建议!

答案 1 :(得分:0)

你需要一个IEqualityComparer,它会根据Ids为你提供不同的对象。

答案 2 :(得分:0)

组密钥是您要分组的内容。您正在混合群组并选择:

var grp=from p in persons
        group p by p.Name into g
        select new {g.Key, Ages=g};

然后你就像这样迭代它:

foreach(var name in grp)
{
  Console.WriteLine(name.Key);

  foreach(var age in name)
    Console.WriteLine("  "+age.Age);
}

这是非常简单的,更好的分组将是:

var grp=from p in persons
        group p by p.Name into g
        select new {Name=g.Key, Ages=from a in g
                                     select a.Age};