Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging two IGrouping sets

Tags:

c#

.net

linq

Suppose I have three users and I want to group them by their country. I would do this:

var users = new[]
{
    new User { Name = "Phil", Country = "UK" },
    new User { Name = "John", Country = "UK" },
    new User { Name = "Mike", Country = "USA" }
};

List<IGrouping<string, User>> groupedUsers
    = users.GroupBy(user => user.Country).ToList();

Now suppose my program gets three more users later on, so I group them too:

var moreUsers = new[]
{
    new User { Name = "Phoebe", Country = "AUS" },
    new User { Name = "Joan", Country = "UK" },
    new User { Name = "Mindy", Country = "USA" }
};

List<IGrouping<string, User>> moreGroupedUsers
    = moreUsers.GroupBy(user => user.Country).ToList();

I now have two seperate groupings, groupedUsers and moreGroupedUsers. How can I merge them into one whilst keeping the grouping valid?

like image 395
Phil K Avatar asked Mar 28 '14 12:03

Phil K


1 Answers

Since the IGrouping<,> API does not provide a mutating interface, you would need to either:

  • simply concatenate and re-group
  • use a mutating container instead, maybe a Dictionary<string, List<User>> to which you can add

The first sounds simpler. It could be either:

var groupedUsers = groupedUsers.SelectMany(grp => grp)
        .Concat(moreUsers)
        .GroupBy(x => x.Country).ToList();

or:

var groupedUsers = users.Concat(moreUsers)
        .GroupBy(x => x.Country).ToList();

(if you still have users available)

The latter could be done with:

var mutable = users.GroupBy(user => user.Country).ToDictionary(
        grp => grp.Key, grp => grp.ToList());

then (to append):

foreach(var user in moreUsers) {
    List<User> list;
    if(!mutable.TryGetValue(user.Country, out list)) {
        mutable.Add(user.Country, list = new List<User>());
    }
    list.Add(user);
}
like image 160
Marc Gravell Avatar answered Oct 18 '22 10:10

Marc Gravell