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

C#中使用LINQ检测并移除对象列表中的重复项

解决ErrorData列表基于内容的重复项检测与移除问题

你的代码失效的核心原因是:默认的引用类型比较是基于对象引用而非内容。LocalizationListData是自定义引用类型,List<KeyValuePair<string, string>>同样是引用类型,即使两个实例的内容完全一致,只要是不同的对象实例,就会被判定为不同的分组键,导致GroupBy无法正确识别重复项。

下面提供两种可靠的解决方案:


方法一:自定义相等比较器(推荐,通用且性能优)

实现IEqualityComparer<ErrorData>,自定义ErrorData的相等逻辑,直接使用Distinct方法完成去重和重复检测。

步骤1:实现自定义相等比较器

public class ErrorDataEqualityComparer : IEqualityComparer<ErrorData>
{
    public bool Equals(ErrorData x, ErrorData y)
    {
        // 处理null情况
        if (ReferenceEquals(x, y)) return true;
        if (x is null || y is null) return false;

        // 先比较Severity和Category
        if (x.Severity != y.Severity || x.Category != y.Category)
            return false;

        // 比较Localisations内部的键值对列表
        var xLocList = x.Localisations?.LstLocalizationData;
        var yLocList = y.Localisations?.LstLocalizationData;

        if (xLocList is null && yLocList is null) return true;
        if (xLocList is null || yLocList is null) return false;
        if (xLocList.Count != yLocList.Count) return false;

        // 若键值对顺序不重要,先排序再比较;顺序重要则直接用SequenceEqual
        var sortedX = xLocList.OrderBy(kv => kv.Key).ThenBy(kv => kv.Value).ToList();
        var sortedY = yLocList.OrderBy(kv => kv.Key).ThenBy(kv => kv.Value).ToList();
        return sortedX.SequenceEqual(sortedY);
    }

    public int GetHashCode(ErrorData obj)
    {
        if (obj is null) return 0;

        // 组合计算哈希值,确保内容相同的对象哈希一致
        int hash = 17;
        hash = hash * 23 + (obj.Severity?.GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Category?.GetHashCode() ?? 0);

        if (obj.Localisations?.LstLocalizationData != null)
        {
            // 同样,若顺序不重要则先排序再计算哈希
            var sortedList = obj.Localisations.LstLocalizationData.OrderBy(kv => kv.Key).ThenBy(kv => kv.Value);
            foreach (var kv in sortedList)
            {
                hash = hash * 23 + kv.Key.GetHashCode();
                hash = hash * 23 + kv.Value.GetHashCode();
            }
        }

        return hash;
    }
}

步骤2:使用比较器完成去重和检测

List<ErrorData> errList = new List<ErrorData>();
// 填充errList数据...

var comparer = new ErrorDataEqualityComparer();
// 检测是否存在重复项
bool hasDups = errList.Count != errList.Distinct(comparer).Count();

// 移除重复项
errList = errList.Distinct(comparer).ToList();

方法二:基于内容生成分组键(快速实现,适合简单场景)

将Localisations的键值对列表转换为可被默认比较器识别的字符串(或其他值类型结构),作为GroupBy的键的一部分。

List<ErrorData> errList = new List<ErrorData>();
// 填充errList数据...

var groupErr = errList.GroupBy(x => new 
{
    x.Severity,
    x.Category,
    // 将键值对排序后拼接成唯一字符串,作为分组依据
    LocalizationKey = x.Localisations?.LstLocalizationData != null 
        ? string.Join("|", x.Localisations.LstLocalizationData
            .OrderBy(kv => kv.Key)
            .ThenBy(kv => kv.Value)
            .Select(kv => $"{kv.Key}:{kv.Value}"))
        : null
});

// 检测重复项
bool hasDups = groupErr.Any(g => g.Count() > 1);

// 移除重复项
if (hasDups)
{
    errList = groupErr.Select(g => g.First()).ToList();
}

注意:如果键或值中包含拼接使用的分隔符(如|),需要替换为不会冲突的特殊字符,避免生成错误的重复键。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:43:34