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

使用Distinct命令无法去除合并后JSON列表重复项的技术咨询

解决Distinct无法去除Order列表重复项的问题

这个问题我碰到过不少次——默认的Distinct()方法对引用类型的判断逻辑和你想的不一样,这就是为啥去重没生效。咱们一步步来解决:

为什么Distinct()没效果?

对于引用类型(比如你的Order类),默认的Distinct()会检查两个对象是否是同一个内存实例,而不是它们的业务属性是否相同。哪怕两个Order对象的所有字段值都完全一致,只要是从两次JSON反序列化得到的不同实例,Distinct()就会把它们当成不同的项。

解决方案

1. 重写Order类的Equals和GetHashCode方法

选一个或多个能唯一标识订单的属性(比如OrderId),基于这些属性实现相等判断:

public class Order
{
    public int OrderId { get; set; }
    // 你的其他属性...

    // 重写Equals方法,判断业务上的相等性
    public override bool Equals(object obj)
    {
        // 先判断是否是同一实例,再判断类型,最后比较关键属性
        if (ReferenceEquals(this, obj)) return true;
        if (obj is null || GetType() != obj.GetType()) return false;
        
        Order otherOrder = (Order)obj;
        return OrderId == otherOrder.OrderId;
    }

    // 重写GetHashCode,基于相同的关键属性计算哈希值
    public override int GetHashCode()
    {
        // 用HashCode.Combine可以方便组合多个属性(如果需要的话)
        return HashCode.Combine(OrderId);
    }
}

修改后直接调用shipments.Distinct().ToList()就能正确去重了。

2. 实现IEquatable<Order>接口(更类型安全的方式)

这是推荐的做法,避免object类型转换的装箱开销,代码更清晰:

public class Order : IEquatable<Order>
{
    public int OrderId { get; set; }
    // 你的其他属性...

    public bool Equals(Order other)
    {
        if (other is null) return false;
        return OrderId == other.OrderId;
    }

    // 重写基类的Equals,调用上面的类型安全版本
    public override bool Equals(object obj) => Equals(obj as Order);

    public override int GetHashCode() => HashCode.Combine(OrderId);
}

3. 使用自定义IEqualityComparer<Order>(不修改原类时用)

如果Order是第三方类或者你不想修改它的代码,可以创建一个单独的比较器:

public class OrderEqualityComparer : IEqualityComparer<Order>
{
    public bool Equals(Order x, Order y)
    {
        if (x is null && y is null) return true;
        if (x is null || y is null) return false;
        return x.OrderId == y.OrderId;
    }

    public int GetHashCode(Order obj)
    {
        return obj.OrderId.GetHashCode();
    }
}

调用时传入这个比较器:

var uniqueShipments = shipments.Distinct(new OrderEqualityComparer()).ToList();

4. 用GroupBy快速去重(临时解决方案)

如果不想写额外的方法或类,可以直接用分组取首项的方式:

var uniqueShipments = shipments
    .GroupBy(order => order.OrderId) // 按唯一标识分组
    .Select(group => group.First())  // 取每组的第一个元素
    .ToList();

注意事项

  • 确保你用来判断重复的属性(比如OrderId)确实能唯一标识一个订单,如果需要多个属性组合判断(比如OrderId + ShipmentId),记得在相等判断和哈希计算里都包含这些属性。
  • 如果用HashCode.Combine,可以传入多个参数,比如HashCode.Combine(OrderId, ShipmentId)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:35:49