2011-05-04 12 views
1

好吧,大家......第一次在这里发布一个问题。我试图演示一些LINQ的功能,并遇到了一些障碍。下面的查询不会达到预期效果: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-to-Objects来说是否正常?再次,这是所有的测试代码。我只是想更好地理解这是如何工作的。我的理解是,当使用匿名对象作为关键字时,它应该对组进行属性和属性的比较。我应该得到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#中。有点奇怪。

回答

0

您需要一个IEqualityComparer,它可以根据Ids为您提供不同的对象。

+0

我知道我需要这样做,如果我在我的复合键中使用自定义类型作为条件,但由于我使用的是匿名类型的字符串,Integer ...我不认为我应该必须实施一个IEqualityCOmparer。它不应该试图比较Person对象。只是钥匙。 – 2011-05-04 17:38:51

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}; 
+0

我在看你的建议,但我不认为结果会做我想要做的事情。我理解你的想法,按照其中一个标准进行分组,然后将子项投影到另一个对象......但如果我有4或5或6个标准,我想分组?我希望它被分组在不同的键上(所有键值的组合)...与我的数据上面,我想结果是一个IEnumerable(的IEnumerable(个人))对象,它应该包含6个项目,其中第一个包含2个项目,其余包含1个项目。 – 2011-05-04 17:36:21

+0

另外,我遇​​到的问题是LINQ for VB.Net中没有Group.Key。我还没有找到一种方法来获得每个组的关键。也许语法不同,但group.key不存在。 – 2011-05-04 17:37:26

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 

现在工作就像一个魅力!感谢您的建议家伙!

+0

我发现为了引用组列,我不得不引用k,而不是g – 2013-06-19 17:38:48