如何逐步构建LINQ GroupBy查询?多维度分组实现方案问询
首先得说清你原来的方案为什么行不通:当你执行var grouped = items.GroupBy(item => item.Color)后,grouped里的每个元素是IGrouping<Color, Item>类型的分组对象,而不是单个的Item。所以你直接对grouped调用GroupBy(item => item.Priority)时,编译器会报错——因为IGrouping<Color, Item>根本没有Priority这个属性,你要的是分组里元素的Priority,不是分组对象本身的。
要实现等价于直接多维度分组(items.GroupBy(item => new { item.Color, item.Priority }))的效果,有两种常见方式,看你需要哪种结构:
方式一:扁平化得到与直接多维度分组完全一致的结果
如果你想要最终的分组集合和直接按(Color, Priority)组合键分组的结果完全一样(每个分组对应一个Color+Priority的组合),可以用SelectMany把每个Color分组内的元素再按Priority分组,然后扁平化这些子分组:
// 第一步:按Color分组 var groupedByColor = items.GroupBy(item => item.Color); // 第二步:遍历每个Color分组,内部按Priority分组,再扁平化所有子分组 var regrouped = groupedByColor.SelectMany(colorGroup => colorGroup.GroupBy(item => new { Color = colorGroup.Key, item.Priority }) );
这样regrouped的每个元素都是IGrouping<匿名类型, Item>,和直接执行items.GroupBy(item => new { item.Color, item.Priority })的分组结构、内容完全等价。
方式二:构建层级化的分组结构
如果你想要保留“先Color分组,再每个Color下按Priority分组”的层级关系(比如需要先遍历Color,再遍历该Color下的Priority分组),可以用Select把每个Color分组转换成包含子分组的对象:
var hierarchicalGroups = items.GroupBy(item => item.Color) .Select(colorGroup => new { ColorKey = colorGroup.Key, PrioritySubGroups = colorGroup.GroupBy(item => item.Priority) });
这种结构下,你可以先循环每个Color分组,再循环该Color下的各个Priority分组,适合需要层级展示数据的场景。
验证等价性
不管用哪种方式,最终的分组数据和直接多维度分组是一致的——比如直接分组得到3个(Color,Priority)组合的分组,分步处理后也会得到相同的3个分组(方式一是直接集合,方式二是包含在Color分组下的子集合)。
内容的提问来源于stack exchange,提问作者Jp_

