You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中对包含内部列表的对象列表按内部列表执行GroupBy分组

问题原因

GroupBy默认使用引用类型的相等比较逻辑,List<xyz>属于引用类型,默认仅对比内存地址,不会校验内部元素是否一致。因此哪怕两个courselist存储的课程完全相同,只要是不同的List实例,就会被判定为不同的分组键,无法分到同一组。

解决方案

方案1:自定义相等比较器(规范实现,性能更好)

首先实现针对List<xyz>的相等比较器:

public class CourseListComparer : IEqualityComparer<List<xyz>>
{
    public bool Equals(List<xyz> x, List<xyz> y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        if (x.Count != y.Count) return false;
        
        // 需忽略课程顺序对分组的影响就用以下代码
        return x.Select(c => c.course).OrderBy(c => c)
            .SequenceEqual(y.Select(c => c.course).OrderBy(c => c));
        
        // 要求课程顺序完全一致才归为同一组就用以下代码替换上面的return
        // return x.Zip(y, (a, b) => a.course == b.course).All(res => res);
    }

    public int GetHashCode(List<xyz> obj)
    {
        if (obj == null) return 0;
        var hash = 17;
        // 和Equals逻辑对应,忽略顺序就保留OrderBy,否则去掉
        foreach (var item in obj.Select(c => c.course).OrderBy(c => c))
        {
            hash = hash * 23 + (item?.GetHashCode() ?? 0);
        }
        return hash;
    }
}

调用GroupBy时传入比较器,同时投影为你需要的结构:

var result = projects.GroupBy(x => x.courselist, new CourseListComparer())
    .Select(g => new 
    {
        courselist = g.Key,
        ids = g.Select(a => a.id).ToList()
    })
    .ToList();

方案2:快速实现(无需自定义类,适合简单场景)

将课程列表拼接为可直接比较的字符串作为分组键:

var result = projects.GroupBy(x => 
    {
        // 忽略顺序就加OrderBy,要求顺序一致就去掉
        var courses = x.courselist.Select(c => c.course).OrderBy(c => c);
        return string.Join("|", courses);
    })
    .Select(g => new 
    {
        courselist = g.First().courselist,
        ids = g.Select(a => a.id).ToList()
    })
    .ToList();

注意

你给出的预期示例ID存在笔误,实际运行后第一组ID为[100, 103],第二组ID为[101]。

内容的提问来源于stack exchange,提问作者Anil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:06:02