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

如何使用自定义IEqualityComparer<T>结合LINQ实现double序列按精度去重

解决方案

可以直接复用LINQ的Distinct方法实现需求,但你当前的DistanceComparer存在关键缺陷,必须先修复GetHashCode的实现才能正常工作。


问题原因

LINQ的Distinct方法执行去重逻辑时,会先调用GetHashCode对元素做哈希分组,只有哈希值相同的元素才会进一步调用Equals判定是否相等。你当前的实现直接抛出异常,会导致运行时报错,且就算不抛异常,如果哈希值不满足「判定为相等的两个元素必须返回相同哈希值」的规则,Equals方法也根本不会被触发,去重逻辑完全失效。


修复后的比较器实现

public class DistanceComparer : IEqualityComparer<double>
{
    public static IEqualityComparer<double> Default { get; } = new DistanceComparer();
    // 容差阈值和缩放系数对应,容差为1e-6时按1e6缩放取整
    private const double Tolerance = 1e-6;
    private const long Scale = 1000000;

    public bool Equals(double x, double y)
    {
        return Math.Abs(x - y) < Tolerance;
    }

    public int GetHashCode(double obj)
    {
        // 按容差缩放后取整,保证判定为相等的元素返回相同哈希码
        long scaled = (long)Math.Round(obj * Scale);
        return scaled.GetHashCode();
    }
}

调用代码

直接调用Distinct的重载方法,传入自定义比较器即可:

var l = new List<double>() { 0, 0 + 1e-7, 1 - 1e-7, 1 };
var distinctResult = l.Distinct(DistanceComparer.Default).ToList();
// 最终输出结果为 [0, 1],符合预期

注意事项

  • 这种基于容差的相等判断不严格满足相等关系的传递性:例如值A和B差0.8e-6、B和C差0.8e-6时,A和B、B和C会被判定为相等,但A和C差1.6e-6会被判定为不等,极端场景下可能出现不符合预期的去重结果。
  • 如果对边界精度要求极高,也可以采用「先排序再相邻比较」的方式实现去重,避免哈希分组的边界误差:
var distinctResult = l.OrderBy(x => x)
    .Aggregate(new List<double>(), (list, current) =>
    {
        if (!list.Any() || Math.Abs(current - list.Last()) >= 1e-6)
            list.Add(current);
        return list;
    });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:27:03