如何对含多类别字段的对象列表按单个类别分组并统计对应对象数量
解决多类别字段的对象数量统计问题
我来帮你搞定这个统计需求!你当前的代码之所以得不到预期结果,核心问题出在分组键的选择上——你用c.Categories(一个List<string>实例)作为分组依据,但列表是引用类型,哪怕两个列表的内容完全一致,只要是不同的实例,GroupBy就会把它们当成不同的组,自然统计不出正确的数量。
正确的实现思路
要统计每个类别对应的对象数量,我们需要先把每个对象的多类别字段拆分成单独的类别条目,再按类别分组统计。具体步骤是:
- 用
SelectMany展开每个对象的所有类别,把一个对应多个类别的对象,拆成多个「类别+对象」的条目; - 以类别字符串作为分组键,统计每个组内的条目数量(每个条目对应一个包含该类别的对象)。
修改后的完整代码
using System; using System.Collections.Generic; using System.Linq; class MyDto { public string Name { get; set; } public List<string> Categories => CategoriesString .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList(); public string CategoriesString { get; set; } public override string ToString() { return Name + ": " + CategoriesString; } } public class Program { public static void Main() { var dtos = new MyDto[] { new MyDto() { Name = "Dto 1", CategoriesString = "DELIVERY"}, new MyDto() { Name = "Dto 2", CategoriesString = "DELIVERY , DAMAGE"}, new MyDto() { Name = "Dto 3", CategoriesString = "DAMAGE"}, new MyDto() { Name = "Dto 4", CategoriesString = "DAMAGE , DELIVERY"}, new MyDto() { Name = "Dto 5", CategoriesString = "DELIVERY"}, }; // 正确的统计逻辑 var res = dtos .SelectMany(dto => dto.Categories) // 展开所有类别 .GroupBy(category => category) // 按类别字符串分组 .Select(g => new { Category = g.Key, Count = g.Count() }); foreach (var item in res) { Console.WriteLine($"{item.Category} - {item.Count}"); } // 输出结果: // DELIVERY - 4 // DAMAGE - 3 } }
为什么这个方法有效?
SelectMany(dto => dto.Categories)会把每个对象的每个类别单独提取出来,比如Dto2会被拆成DELIVERY和DAMAGE两个独立条目;- 用
category字符串作为分组键,相同的类别会被归到同一组; - 最后
g.Count()统计的就是包含该类别的对象总数,完全符合你的预期。
另外,你提到数据来自EF Core且会在客户端执行,这个逻辑完全没问题——SelectMany和后续的分组统计都会被EF Core识别为客户端评估操作,不会尝试转换成SQL,和你的需求匹配。
内容的提问来源于stack exchange,提问作者sommmen
相关产品推荐
相关产品推荐

