使用 Linq 将对象列表分组为新的对象列表分组列表
Posted
技术标签:
【中文标题】使用 Linq 将对象列表分组为新的对象列表分组列表【英文标题】:Using Linq to group a list of objects into a new grouped list of list of objects 【发布时间】:2011-02-11 10:33:18 【问题描述】:我不知道这在 Linq 中是否可行,但这里是……
我有一个对象:
public class User
public int UserID get; set;
public string UserName get; set;
public int GroupID get; set;
我返回的列表可能如下所示:
List<User> userList = new List<User>();
userList.Add( new User UserID = 1, UserName = "UserOne", GroupID = 1 );
userList.Add( new User UserID = 2, UserName = "UserTwo", GroupID = 1 );
userList.Add( new User UserID = 3, UserName = "UserThree", GroupID = 2 );
userList.Add( new User UserID = 4, UserName = "UserFour", GroupID = 1 );
userList.Add( new User UserID = 5, UserName = "UserFive", GroupID = 3 );
userList.Add( new User UserID = 6, UserName = "UserSix", GroupID = 3 );
我希望能够在上述列表上运行 Linq 查询,按 GroupID 对所有用户进行分组。所以输出将是一个包含用户的用户列表列表(如果有意义的话?)。比如:
GroupedUserList
UserList
UserID = 1, UserName = "UserOne", GroupID = 1
UserID = 2, UserName = "UserTwo", GroupID = 1
UserID = 4, UserName = "UserFour", GroupID = 1
UserList
UserID = 3, UserName = "UserThree", GroupID = 2
UserList
UserID = 5, UserName = "UserFive", GroupID = 3
UserID = 6, UserName = "UserSix", GroupID = 3
我尝试过使用 groupby linq 子句,但这似乎返回了一个键列表并且它没有正确分组:
var groupedCustomerList = userList.GroupBy( u => u.GroupID ).ToList();
【问题讨论】:
【参考方案1】:var groupedCustomerList = userList
.GroupBy(u => u.GroupID)
.Select(grp => grp.ToList())
.ToList();
【讨论】:
非常好,正是我需要的。谢谢。这样做很糟糕。 工作正常吗?因为我习惯了这种方式并没有奏效。 objModel.tblDonars.GroupBy(t => new t.CreatedOn.Year, t.CreatedOn.Month, t.CreatedOn.Day ).Select(g => new tblDonar = g.ToList() ).ToList( );这不起作用......你能帮忙...... 使用您的解决方案可以正常工作,但我有一个问题,假设组中最多 8 个值,我只想在每个组中只需要 6 次,所以如何做到这一点请告诉我。 按GroupID分组后有没有办法分别列出UserNames和UserIDs?比如 - "1", [1, 2, 4], ["UserOne", "UserTwo", "UserFour"] 用于 groupID 1。 当前代码不起作用,如果您尝试将其转换为以前的列表类型,则会导致错误。因为在 select 中返回一个列表会在列表中创建一个列表,这不是此处所需的输出。对于那些有问题的人,我可以建议: var groupedCustomerList = userList.GroupBy(u => u.GroupID).Select(grp => grp.First()).ToList();【参考方案2】:您的组声明将按组 ID 分组。例如,如果你接着写:
foreach (var group in groupedCustomerList)
Console.WriteLine("Group 0", group.Key);
foreach (var user in group)
Console.WriteLine(" 0", user.UserName);
应该可以正常工作。每个组有一个键,但还包含一个IGrouping<TKey, TElement>
,它是一个允许您遍历组成员的集合。正如 Lee 所提到的,如果您真的想要,您可以将每个组转换为一个列表,但如果您只是按照上面的代码对它们进行迭代,那么这样做并没有真正的好处。
【讨论】:
【参考方案3】:对于类型
public class KeyValue
public string KeyCol get; set;
public string ValueCol get; set;
收藏
var wordList = new Model.DTO.KeyValue[]
new Model.DTO.KeyValue KeyCol="key1", ValueCol="value1" ,
new Model.DTO.KeyValue KeyCol="key2", ValueCol="value1" ,
new Model.DTO.KeyValue KeyCol="key3", ValueCol="value2" ,
new Model.DTO.KeyValue KeyCol="key4", ValueCol="value2" ,
new Model.DTO.KeyValue KeyCol="key5", ValueCol="value3" ,
new Model.DTO.KeyValue KeyCol="key6", ValueCol="value4"
;
我们的 linq 查询如下所示
var query =from m in wordList group m.KeyCol by m.ValueCol into g
select new Name = g.Key, KeyCols = g.ToList() ;
或用于数组而不是下面的列表
var query =from m in wordList group m.KeyCol by m.ValueCol into g
select new Name = g.Key, KeyCols = g.ToList().ToArray<string>() ;
【讨论】:
【参考方案4】:仍然是旧的,但李的回答没有给我 group.Key 结果。因此,我使用以下语句对列表进行分组并返回分组列表:
public IOrderedEnumerable<IGrouping<string, User>> groupedCustomerList;
groupedCustomerList =
from User in userList
group User by User.GroupID into newGroup
orderby newGroup.Key
select newGroup;
现在每个组都有一个键,但还包含一个 IGrouping,它是一个允许您迭代组成员的集合。
【讨论】:
这回答了 your 的问题,而不是 OP 的问题。他们只想要一个列表列表。您的代码没有提供。 我已经发布了这个解决方案,因为上面从@Lee 接受的答案在迭代时不起作用,因为它在迭代分组列表时提供了group.key
元素,例如在@JohnSkeet 的回答中显示。我提供的答案确实在迭代时提供了 group.key 元素。因此,它可能有助于其他人陷入所提供的答案不起作用的陷阱,如上所示。因此,这只是获取列表的另一种方法,它可以让 group.key 元素类似于已接受的答案。不明白你的主张@GertArnold。 (.net core 3.0)
我认为整个问题是基于缺乏对IGrouping
的理解。这就是为什么 OP 在底部丢弃他们自己的正确代码,这与您的代码基本相同。这就是为什么他们接受一个能提供他们所要求的答案的原因。他们需要的是解释,JS充分提供了。以上是关于使用 Linq 将对象列表分组为新的对象列表分组列表的主要内容,如果未能解决你的问题,请参考以下文章