C# Linq Group By on multiple columns

C#LinqGroup ByAggregate

C# Problem Overview


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

Given the two classes above, I would like to use LINQ to create a List from the List, grouped by the School, Friend and FavoriteColor properties. Is this possible with LINQ?

Please ignore the properties, the code has been written just to help with the question.

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

Given a list:

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"},
};

The query would look like:

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

Test code:

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

Result:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKasyView Question on Stackoverflow
Solution 1 - C#EnigmativityView Answer on Stackoverflow
Solution 2 - C#JamiecView Answer on Stackoverflow