【问题标题】:Nested GroupBy LINQ Using Fluent Syntax使用流畅语法的嵌套 GroupBy LINQ
【发布时间】:2016-08-17 15:54:47
【问题描述】:

我正在尝试使用流畅(即“方法”)语法编写嵌套的 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" }
};

我想要实现的是由ZipCodeGenderZipCode 中分组的对象。就对象类型而言,我正在寻找这个:

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);
        }

    }
}

【问题讨论】:

    标签: linq group-by


    【解决方案1】:

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

    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;
    

    并使用“流利的”语法将其转换为:

    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)
        );
    

    【讨论】:

    • 超级反直觉(我总是忘记这样做后的模式是什么),但可以。酷:)
    【解决方案2】:

    以下内容:

    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);
    
        }
    }
    

    会写出以下内容:

    邮编:11111

    性别:男

    汤姆

    鲍勃

    性别:F

    南希

    丽莎

    邮编:22222

    性别:男

    邮编:33333

    性别:F

    玛丽

    邮编:44444

    性别:F

    性别:男

    比尔

    这是你想要的吗?

    (我意识到它不完全是 IEnumerable>>> 但我认为它更像是您感兴趣的数据的形状,是一种精确的类型) .

    【讨论】:

    • 这行得通,但我有点坚持得到我提到的所需类型。弄不明白真烦人。
    • 虽然不是完全符合 OP 要求,但我发现这种安排更容易阅读以获得相同的结果,所以这是我的 +1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    相关资源
    最近更新 更多