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

如何检查嵌套字典对象相等性并移除List<Row>中的重复项?

解决Row列表去重与嵌套字典相等性检查问题

一、核心前提:Column类的相等性处理

因为Dictionary<Column, Cell>的键是Column类型,默认的引用相等逻辑会导致键匹配出错,所以必须让Column实现值相等逻辑。假设Column用ColumnId作为唯一标识,重写如下:

public class Column
{
    public int ColumnId { get; set; }
    // 其他属性...

    public override bool Equals(object obj)
    {
        return obj is Column column && ColumnId == column.ColumnId;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(ColumnId);
    }
}

二、嵌套字典的相等性检查逻辑

默认的Dictionary.Equals只比较引用是否相同,要判断两个Dictionary<Column, Cell>内容相等,需满足:

  1. 两个字典的键集合完全一致(数量相同、每个键都存在于对方字典)
  2. 每个键对应的Cell.Value完全相等

方案1:独立的字典比较器

可以封装一个可复用的字典比较器:

public class ColumnCellDictionaryComparer : IEqualityComparer<Dictionary<Column, Cell>>
{
    public bool Equals(Dictionary<Column, Cell> x, Dictionary<Column, Cell> y)
    {
        if (x == y) return true;
        if (x == null || y == null) return false;
        if (x.Count != y.Count) return false;

        foreach (var kvp in x)
        {
            if (!y.TryGetValue(kvp.Key, out var targetCell))
                return false;
            if (kvp.Value.Value != targetCell.Value)
                return false;
        }
        return true;
    }

    public int GetHashCode(Dictionary<Column, Cell> obj)
    {
        if (obj == null) return 0;
        int hash = 17;
        // 排序保证哈希码不受键的遍历顺序影响
        foreach (var kvp in obj.OrderBy(k => k.Key.ColumnId))
        {
            hash = hash * 31 + kvp.Key.GetHashCode();
            hash = hash * 31 + (kvp.Value.Value?.GetHashCode() ?? 0);
        }
        return hash;
    }
}

三、修正RowEqualityComparer并实现去重

你写的原始比较器存在两个关键问题:

  • a.Cells.Equals(b.Cells)是引用比较,无法判断内容相等
  • GetHashCode直接返回对象的默认哈希码,导致相同内容的Row无法被Distinct识别

修正后的实现如下:

public class RowEqualityComparer : IEqualityComparer<Row>
{
    private readonly ColumnCellDictionaryComparer _dictComparer = new ColumnCellDictionaryComparer();

    public bool Equals(Row a, Row b)
    {
        if (a == b) return true;
        if (a == null || b == null) return false;

        // 若只需根据Cells的Value去重,忽略Id和Name,就只保留下面的判断
        // 若需要同时校验Id/Name,添加对应的判断:a.Id == b.Id && a.Name == b.Name && ...
        return _dictComparer.Equals(a.Cells, b.Cells);
    }

    public int GetHashCode(Row obj)
    {
        if (obj == null) return 0;
        // 与Equals逻辑对应,仅基于Cells生成哈希码
        return _dictComparer.GetHashCode(obj.Cells);
    }
}

四、执行去重操作

使用修正后的比较器,直接调用Distinct即可完成去重:

List<Row> originalRows = GetYourRowList(); // 替换为你的原始Row列表
List<Row> uniqueRows = originalRows.Distinct(new RowEqualityComparer()).ToList();

补充说明

  • 若Cell.Value可能为null,当前代码已经兼容(C#中null != null结果为false,符合空值相等的预期)
  • 如果去重逻辑需要包含Row.Id或Row.Name,只需在Equals中添加对应判断,并在GetHashCode中合并这些属性的哈希值

内容的提问来源于stack exchange,提问作者Sebastián Rubina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 18:35:28