C# Linq Group By 在多列上[重复]

Posted

技术标签:

【中文标题】C# Linq Group By 在多列上[重复]【英文标题】:C# Linq Group By on multiple columns [duplicate] 【发布时间】:2011-07-11 01:13:37 【问题描述】:
public class ConsolidatedChild

    public string School  get; set; 
    public string Friend  get; set; 
    public string FavoriteColor  get; set; 
    public List<Child> Children  get; set; 


public class Child

    public string School  get; set; 
    public string Name  get; set; 
    public string Address  get; set; 
    public string Friend  get; set; 
    public string Mother  get; set; 
    public string FavoriteColor  get; set; 

鉴于上述两个类,我想使用 LINQ 从列表中创建一个列表,按 School、Friend 和 FavoriteColor 属性分组。 LINQ 可以做到这一点吗?

请忽略属性,编写代码只是为了帮助解决问题。

【问题讨论】:

是的,这是可能的。查看this 帖子中提供的示例。 这是另一个很好的例子***.com/questions/15605468/… 【参考方案1】:
var consolidatedChildren =
    from c in children
    group c by new
    
        c.School,
        c.Friend,
        c.FavoriteColor,
     into gcs
    select new ConsolidatedChild()
    
        School = gcs.Key.School,
        Friend = gcs.Key.Friend,
        FavoriteColor = gcs.Key.FavoriteColor,
        Children = gcs.ToList(),
    ;

var consolidatedChildren =
    children
        .GroupBy(c => new
        
            c.School,
            c.Friend,
            c.FavoriteColor,
        )
        .Select(gcs => new ConsolidatedChild()
        
            School = gcs.Key.School,
            Friend = gcs.Key.Friend,
            FavoriteColor = gcs.Key.FavoriteColor,
            Children = gcs.ToList(),
        );

【讨论】:

假设我在 group by 中有很多属性,有没有一种更简洁的方法来列出所有属性? @guiomie - 我不会说有更清洁的方法。您可以将对象序列化为单个字符串并对其进行分组,但这需要其他地方的更多代码。所以,在我看来,无论有多少属性,这个答案都是最干净的方法。 @Doppelganger - 我回滚了你的编辑有两个原因。选择使用最后的逗号(在FavoriteColor 之后)是有目的的——它是合法的语法,并且可以更轻松地重构代码。选择使用gcs 而不是gc 作为分组变量也是有目的的——它告诉我它是一个“许多c 的组”。 我认为肯定不会编译,但你是绝对正确的。至于重命名你的变量,那只是为了超过六个字符的限制。我从不喜欢弄乱某人的变量名。无论如何,再次感谢您的精彩回答! @AlexanderRyanBaggett - 完成。【参考方案2】:

给定一个列表:

var list = new List<Child>()

    new Child()
        School = "School1", FavoriteColor = "blue", Friend = "Bob", Name = "John",
    new Child()
        School = "School2", FavoriteColor = "blue", Friend = "Bob", Name = "Pete",
    new Child()
        School = "School1", FavoriteColor = "blue", Friend = "Bob", Name = "Fred",
    new Child()
        School = "School2", FavoriteColor = "blue", Friend = "Fred", Name = "Bob",
;

查询看起来像:

var newList = list
    .GroupBy(x => new x.School, x.Friend, x.FavoriteColor)
    .Select(y => new ConsolidatedChild()
        
            FavoriteColor = y.Key.FavoriteColor,
            Friend = y.Key.Friend,
            School = y.Key.School,
            Children = y.ToList()
        
    );

测试代码:

foreach(var item in newList)

    Console.WriteLine("School: 0 FavouriteColor: 1 Friend: 2", item.School,item.FavoriteColor,item.Friend);
    foreach(var child in item.Children)
    
        Console.WriteLine("\t Name: 0", child.Name);
    

结果:

School: School1 FavouriteColor: blue Friend: Bob
    Name: John
    Name: Fred
School: School2 FavouriteColor: blue Friend: Bob
    Name: Pete
School: School2 FavouriteColor: blue Friend: Fred
    Name: Bob

【讨论】:

适合我们这些喜欢流畅界面的人。一个小问题:在两个 Func 定义中使用相同的变量“x”对于新用户来说并不是很清楚。我建议更改以匹配上面的那个,其中“c”是孩子,“gcs”是分组的孩子。 @jazmatician _ 我同意你的观点,即重复使用 x 可能会使一些人感到困惑,但在变量名的选择上不会。我将其更改为xy 以区分。 变量名也不是我的选择。事实上,当我写这篇文章时,我很难弄清楚“gcs”对作者意味着什么。我能想到的最好的办法是“一组(的)Cs”。无论如何,我只推荐它以尝试让某人更容易地在两种语法之间制作思维导图。 (句法?我敢打赌,syntax 是它自己的复数词之一。因为这是英语,为什么“syntax”要服从关于复数的句法规则?) 回答我自己的切线:en.wiktionary.org/wiki/syntax 我不同意迈克尔的这个观点。在我看来,x 应该在两个地方都使用。唯一不应该的情况是当你使用一个 Func 和另一个 Hunc 时,你应该去 y。否则会变得混乱。

以上是关于C# Linq Group By 在多列上[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在linq C#中使用group by并获取记录列表[重复]

C# Linq group by 和 group by into 运用实例

inq to datatable group by 多列 实现

如何通过 join 和 group by 在 C# Linq 中获取 Min?

C# Linq to SQL — Group by

c# Linq select join on select group by