合并两个IGrouping集合

15

假设我有三个用户,我想按照他们的国家对他们进行分组。我会这样做:

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

现在假设我的程序后来又获得了三个用户,所以我也将他们分组:

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

我现在有两个独立的分组,groupedUsersmoreGroupedUsers。如何将它们合并成一个,同时保持分组有效?


归并排序是最直接的答案,你只需要将一个列表添加到另一个列表中,然后再次进行排序。 - knightsb
2个回答

16

由于 IGrouping<,> API 不提供可变接口,因此您需要采取以下措施之一:

  • 简单地连接和重新分组
  • 改用可变容器,例如 Dictionary<string, List<User>>,您可以向其中添加元素

第一个听起来更简单。它可能是:

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

(如果你仍然有可用的用户)

后者可以通过以下方式完成:

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

然后(追加):

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

0

我知道有点晚了,但这可能会帮助其他想避免使用Dictionary类的人。虽然,这个“解决方案”可能会对大型集合和重复执行造成性能问题。

你只需要使用IEnumerable.SelectMany方法来展开users组集合,然后使用Enumerable.Concat方法将新元素连接到展开的集合中,最后再次使用IEnumerable.GroupBy方法重新分组元素。

例如:

var flattenedUsers = users.SelectMany(users => users);
var result = Enumerable.Concat(flattenedUsers, moreUsers).GroupBy(users.Country);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接