嵌套GroupBy LINQ使用流畅语法

时间:2016-08-17 15:54:47

标签: linq group-by

我正在尝试使用流利(即“方法”)语法编写嵌套的GroupBy LINQ表达式。

这是我的课程和数据:

class Person
{
    public String ZipCode, Gender, Name;
}

private static List<Person> people = new List<Person>
{
    new Person { ZipCode= "11111", Gender = "M", Name = "Tom" },
    new Person { ZipCode= "11111", Gender = "M", Name = "Bob" },
    new Person { ZipCode= "11111", Gender = "F", Name = "Nancy" },
    new Person { ZipCode= "11111", Gender = "F", Name = "Lisa" },
    new Person { ZipCode= "22222", Gender = "M", Name = "Dan" },
    new Person { ZipCode= "33333", Gender = "F", Name = "Mary" },
    new Person { ZipCode= "44444", Gender = "F", Name = "Joan" },
    new Person { ZipCode= "44444", Gender = "F", Name = "Jane" },
    new Person { ZipCode= "44444", Gender = "M", Name = "Bill" }
};

我想要实现的是一个对象,按ZipCode分组,然后Gender分组ZipCode。就对象类型而言,我正在寻找:

IEnumerable<IGrouping<string, IEnumerable<IGrouping<string, Person>>>>

这样我就可以像这样访问查询结果:

foreach(var byZip in mainQuery) {
   Console.WriteLine(byZip.Key);  // print the ZipCode
   foreach(var byGender in byZip) {
      Console.WriteLine(byGender.Key) // print the Gender
      foreach (Person p in byGender)
         Console.WriteLine(p.Name);
   }
}

同样,我希望使用流利的符号。

根据Jeff的回答,这是查询和访问:

IEnumerable<IGrouping<string, IEnumerable<IGrouping<string, Person>>>> query = 
    people
        .GroupBy(p => p.ZipCode)
            .GroupBy(
                keySelector: g => g.Key,
                elementSelector: g => g.GroupBy(p => p.Gender)
            );


foreach (IGrouping<string, IEnumerable<IGrouping<string, Person>>> byZip in query)
{
    Console.WriteLine(byZip.Key);  // print the ZipCode
    foreach (IEnumerable<IGrouping<string, Person>> byGender in byZip)
    {
        foreach (IGrouping<string, Person> t in byGender)
        { 
            Console.WriteLine(t.Key); // print the Gender
            foreach (Person y in t)
                Console.WriteLine(y.Name);
        }

    }
}

2 个答案:

答案 0 :(得分:7)

在查询语法中,您可以这样写:

var query =
    from p in people
    group p by p.ZipCode into g
    let gender =
        from p in g
        group p by p.Gender
    group gender by g.Key;

使用&#34;流利的&#34;转换它语法,这将成为这个:

var query2 = people.GroupBy(p => p.ZipCode)
    .GroupBy(
        g => g.Key,
        g => g.GroupBy(p => p.Gender)
    );

但是,您想要访问它的方式与实际类型不匹配。您的访问模式实际上是您的类型:

IEnumerable<IGrouping<string, IGrouping<string, Person>>>

所以查询应该是:

var query =
    from p in people
    group p by p.ZipCode into g
    let gender =
        from p in g
        group p by p.Gender
    from g2 in gender
    group g2 by g.Key;

转换......有点复杂。

var query2 = people.GroupBy(p => p.ZipCode)
    .SelectMany(g =>
        g.GroupBy(p => p.Gender).GroupBy(g2 => g.Key)
    );

答案 1 :(得分:0)

以下内容:

var peopleGroupedByZipCode = people
    .GroupBy(p => p.ZipCode)
    .Select(group => new
    {
        ZipCode = group.Key,
        PeopleGroupedByGender = group.GroupBy(p => p.Gender)
    });

foreach (var resultsByZipCode in peopleGroupedByZipCode)
{
    Console.WriteLine("ZipCode: " + resultsByZipCode.ZipCode);
    foreach (var resultsByGender in resultsByZipCode.PeopleGroupedByGender)
    {
        Console.WriteLine(" Gender : " + resultsByGender.Key);
        foreach (var resultWithinGenderGroup in resultsByGender)
            Console.WriteLine("  " + resultWithinGenderGroup.Name);

    }
}

将写出以下内容:

  

ZipCode:11111

     

性别:M

     

汤姆

     

鲍勃

     

性别:F

     

南西

     

莉莎

     

ZipCode:22222

     

性别:M

     

     

ZipCode:33333

     

性别:F

     

玛丽

     

ZipCode:44444

     

性别:F

     

     

     

性别:M

     

比尔

这是你想要的那种吗?

(我意识到它不是一个IEnumerable&lt; IGrouping&lt; string,IEnumerable&lt; IGrouping&lt; string,Person&gt;&gt;&gt;&gt;但我认为它更像是你感兴趣的数据的形状精确型)。