230

This question already has an answer here:

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.


2 답변


360

Easy:

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


  • Let's say I have lot's of properties in the group by, is there a cleaner way of doing this then listing all the properties? - guiomie
  • @guiomie - I wouldn't say that there was a cleaner way. You could serialize the object into a single string and group on that, but that would require more code elsewhere. So, in my mind, this answer is the cleanest way regardless how many properties. - Enigmativity
  • @Doppelganger - I rolled back your edit for two reasons. The choice of using the final comma (after FavoriteColor) is on purpose - it is legal syntax and it enables easier refactoring of code. The choice of using gcs rather than gc for the grouping variable is also on purpose - it shows me that it is a "group of many c's". - Enigmativity
  • I thought for sure that wouldn't compile, but you're absolutely right. As for renaming your variable, that was just to get past the six character limit. I never like to mess with someone's variable names. Anyway, thanks again for the awesome answer! - Doppelganger

184

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


  • For those of us who prefer the fluent interface. One tiny quibble: using the same variable "x" in both Func definitions isn't very clear for newer users. I'd recommend changing to match the one above, where "c" is the child, and "gcs" is the grouped children. - Michael Blackburn
  • @jazmatician _ I agree with you on the point that re-using x might confuse some, but not on the choice for variable names. I'll change it to x and y to diferentiate. - Jamiec
  • The variable names aren't my choice, either. In fact, when writing that I struggled to figure out what "gcs" meant to the author. Best I could come up with was "group (of) Cs." Anyway, I only recommended it to try to make it easy for someone to make the mental map between the two syntaxes. (syntaces? I bet syntax is one of those words which is its own plural. Because this is English, why would "syntax" be subject to syntactic rules about plurals?) - Michael Blackburn
  • to answer my own tangent: en.wiktionary.org/wiki/syntax - Michael Blackburn
  • I disagree with this opinion Michael. In my opinion, x should be used in both places. The only time it should not is when you use a Func withing another Hunc, then you should go to y. Otherwise it becomes confusing. - Serj Sagan

Linked


Related

Latest