Home > front end >  How to concatenate multiple rows list with same value into single row
How to concatenate multiple rows list with same value into single row

Time:02-10

I have the following class called "Person".

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }    
    public string Hobby { get; set; }
}

I created a list with the following data:

List<Person> users = new List<Person>()
{
    new Person {Id= 1, Name = "Silva", Hobby = "Football" },
    new Person {Id= 2, Name = "Bob", Hobby = "Golf"},
    new Person {Id= 2, Name = "Bob", Hobby = "Tennis"},
    new Person {Id= 1, Name = "Silva", Hobby = "Sleeping"},
    new Person {Id= 3, Name = "Sue", Hobby = "Drinking"}
    new Person {Id= 1, Name = "Silva", Hobby = "Handball"},
    new Person {Id= 3, Name = "Sue", Hobby = "Football"},
};

Now I need to create a new list called "usersHobbies" that when called returns the following result.

Id    Name        Hobby 
1     Silva       Football, Sleeping, Handball   
2     Bob         Golf, Tennis
3     Sue         Drinking, Football             

CodePudding user response:

You would use result showing 3 rows

If you want to return a new Person instead of an anonymous type, just update the Select:

 .Select(g => new Person
  { 
      Id = g.Key, 
      Name = g.First().Name, 
      Hobby = string.Join(", ", g.Select(u => u.Hobby)) 
  })

Update from your comment:

is it possible instead of string.join() to return a list or array

Yes, it is. Using an anonymous type:

var result = users.GroupBy(u => u.Id)  // group by Id
                  .Select(g => new     // select values
                  { 
                      Id = g.Key, 
                      Name = g.First().Name, 
                      Hobbies = g.Select(u => u.Hobby).ToList() 
                  })
                  .ToList();

Which returns a List<string> for Hobbies.

CodePudding user response:

.GroupBy() has an override that lets you define a key selector, an element selector and the result selector (docs), which could suit your use case:

var result = users
    .GroupBy(
        u => new { u.Id, u.Name }, // key selector
        u => u.Hobby, // element selector
        (user, hobbies) => new Person { 
            Id = user.Id, 
            Name = user.Name, 
            Hobby = string.Join(", ", hobbies) })
    .ToList();

Here, (user, hobbies) are referencing the key selector and the element selector, respectively.

What happens is:

  • the users are grouped into unique users based on the combination of Id and Name (key selector)
  • the hobbies of each unique user are collected into an IEnumerable<string> (element selector)
  • for each unique user, a Person object is created and populated with all of the users hobbies.
  • Related