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

如何高效确保Address列表中address属性的唯一性?

确保Address列表中address属性唯一性的高效实现方案

问题背景

现有以下C#类定义:

public class Address
{
    public List<AddressElement>? address;
    public int weight;
    public int missingComponents;
}

public class AddressElement
{
    public uint Id { get; set; }
    public uint ObjectId { get; set; }
    public Guid ObjectGuid { get; set; }
    public string Name { get; set; }
    public byte Level { get; set; }
    public string UpdateDate { get; set; }
    // 其他属性
    public bool IsActual { get; set; }
    public bool IsActive { get; set; }
}

声明了地址列表:

List<Address> addresses = new();

需求:保证列表中每个Address对象的address属性(List<AddressElement>?类型)具有唯一性,即不存在两个Address的address列表完全相同。


核心思路

由于List<AddressElement>是引用类型,默认比较的是引用地址而非内容,因此需要自定义内容相等判断逻辑,再基于此实现列表的唯一性校验。

步骤1:定义AddressElement的相等规则

首先确定两个AddressElement何时视为相等。从属性来看,ObjectGuid是全局唯一标识,以此作为相等判断依据最可靠:

public class AddressElement
{
    // 原有属性...

    // 重写Equals判断元素相等
    public override bool Equals(object? obj)
    {
        return obj is AddressElement element && ObjectGuid.Equals(element.ObjectGuid);
    }

    // 重写GetHashCode配合Equals使用
    public override int GetHashCode()
    {
        return ObjectGuid.GetHashCode();
    }
}

注:如果需要结合多个属性判断相等(比如Name+Level),可以修改Equals和GetHashCode的逻辑。

步骤2:实现Address的自定义比较器

创建IEqualityComparer<Address>的实现类,用来判断两个Address的address列表是否内容相同:

public class AddressEqualityComparer : IEqualityComparer<Address>
{
    public bool Equals(Address? x, Address? y)
    {
        // 处理null场景
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        if (x.address == null && y.address == null) return true;
        if (x.address == null || y.address == null) return false;

        // 列表长度不同直接不相等
        if (x.address.Count != y.address.Count) return false;

        // 方案A:严格按顺序比较(地址层级通常有顺序要求,比如省→市→区不能乱)
        for (int i = 0; i < x.address.Count; i++)
        {
            if (!x.address[i].Equals(y.address[i]))
                return false;
        }
        return true;

        // 方案B:不考虑顺序,只要元素集合相同即相等
        // return new HashSet<AddressElement>(x.address).SetEquals(y.address);
    }

    public int GetHashCode(Address obj)
    {
        if (obj.address == null) return 0;

        // 组合列表所有元素的哈希值,生成当前Address的哈希码
        int hash = 17;
        foreach (var element in obj.address)
        {
            hash = hash * 31 + element.GetHashCode();
        }
        return hash;
    }
}

步骤3:高效维护唯一性列表

方式一:用HashSet自动去重(推荐,效率更高)

HashSet会基于自定义比较器自动判断元素是否重复,添加时直接过滤重复项,查找时间复杂度为O(1):

var addressComparer = new AddressEqualityComparer();
HashSet<Address> uniqueAddresses = new HashSet<Address>(addressComparer);

// 添加元素时自动去重
uniqueAddresses.Add(new Address
{
    address = new List<AddressElement> { /* 初始化元素 */ },
    weight = 2,
    missingComponents = 0
});

// 如需转为List
List<Address> addresses = uniqueAddresses.ToList();

方式二:手动检查后添加到List

如果必须使用List,在添加前用比较器检查是否已存在(时间复杂度O(n),适合小体量数据):

var addressComparer = new AddressEqualityComparer();
List<Address> addresses = new();

var newAddress = new Address { /* 初始化 */ };
if (!addresses.Any(a => addressComparer.Equals(a, newAddress)))
{
    addresses.Add(newAddress);
}

注意事项

  • 若地址列表的顺序不影响唯一性,可切换到比较器中的方案B(用HashSet.SetEquals)
  • 务必处理address为null的边界场景,避免空引用异常
  • 自定义比较器的方式比直接重写Address的Equals更灵活,不会影响类在其他场景的默认行为

内容的提问来源于stack exchange,提问作者Александр Попов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:54:55