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

使用Linq Union合并集合:规避空值与重复数据

使用LINQ Union合并两个集合并避免空值与重复数据

要实现这个需求,我们需要分两步走:先过滤掉无效的空值条目,再通过自定义相等逻辑实现Union去重。下面是具体的实现方案:

1. 第一步:过滤空值条目

首先,我们需要从两个集合中剔除那些关键字段为空的无效数据——比如VoteFunction、Area、Sector这些用来标识唯一性的字段,以及邮箱类字段全为空的条目(你可以根据实际业务需求调整过滤规则):

// 过滤VoteData集合中的空值
var filteredVoteData = voteDataList
    .Where(v => !string.IsNullOrEmpty(v.VoteFunction) 
             && !string.IsNullOrEmpty(v.Area) 
             && !string.IsNullOrEmpty(v.Sector)
             && (!string.IsNullOrEmpty(v.Email) || !string.IsNullOrEmpty(v.VoterEmail)));

// 过滤DirectoryData集合中的空值
var filteredDirectoryData = directoryDataList
    .Where(d => !string.IsNullOrEmpty(d.VoteFunction) 
             && !string.IsNullOrEmpty(d.Area) 
             && !string.IsNullOrEmpty(d.Sector)
             && (!string.IsNullOrEmpty(d.PrimaryEmail) || !string.IsNullOrEmpty(d.VoterEmail)));

2. 第二步:合并与去重

因为VoteData和DirectoryData是不同的类,我们有两种常见的合并方式:

方式一:投影到匿名类型(简单快捷)

把两个集合投影成结构一致的匿名类型,利用匿名类型默认的属性相等性(Equals和GetHashCode会自动比较所有属性)来实现Union去重:

// 将VoteData投影为统一结构
var voteProjections = filteredVoteData.Select(v => new {
    v.VoteFunction,
    v.Area,
    v.Sector,
    Email = v.Email ?? v.VoterEmail, // 优先取Email,为空则用VoterEmail
    v.VoterEmail
});

// 将DirectoryData投影为统一结构
var directoryProjections = filteredDirectoryData.Select(d => new {
    d.VoteFunction,
    d.Area,
    d.Sector,
    Email = d.PrimaryEmail ?? d.VoterEmail, // 优先取PrimaryEmail,为空则用VoterEmail
    d.VoterEmail
});

// 合并并去重
var mergedResult = voteProjections.Union(directoryProjections).ToList();

方式二:转换为同一类型+自定义相等比较器(保留原始类型)

如果你需要保留VoteData类型的实例,可以先把DirectoryData转换成VoteData,再通过自定义IEqualityComparer来定义“重复”的规则:

第一步:转换DirectoryData为VoteData

var directoryAsVoteData = filteredDirectoryData.Select(d => new VoteData {
    Name = null, // DirectoryData没有Name字段,根据需求填充默认值或null
    VoteFunction = d.VoteFunction,
    Area = d.Area,
    Sector = d.Sector,
    Email = d.PrimaryEmail,
    VoterEmail = d.VoterEmail
});

第二步:实现自定义相等比较器

public class VoteDataEqualityComparer : IEqualityComparer<VoteData>
{
    public bool Equals(VoteData x, VoteData y)
    {
        if (x == null || y == null)
            return x == y;
        
        // 自定义重复规则:VoteFunction+Area+Sector相同,且邮箱(Email/VoterEmail)有一个匹配就算重复
        return string.Equals(x.VoteFunction, y.VoteFunction, StringComparison.OrdinalIgnoreCase)
            && string.Equals(x.Area, y.Area, StringComparison.OrdinalIgnoreCase)
            && string.Equals(x.Sector, y.Sector, StringComparison.OrdinalIgnoreCase)
            && (string.Equals(x.Email, y.Email, StringComparison.OrdinalIgnoreCase) 
                || string.Equals(x.VoterEmail, y.VoterEmail, StringComparison.OrdinalIgnoreCase));
    }

    public int GetHashCode(VoteData obj)
    {
        if (obj == null)
            return 0;
        
        // 基于关键字段计算哈希码,确保Equals返回true的对象哈希码一致
        int hash = 17;
        hash = hash * 23 + (obj.VoteFunction?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Area?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Sector?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Email?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.VoterEmail?.ToLower().GetHashCode() ?? 0);
        return hash;
    }
}

第三步:执行Union合并

var mergedResult = filteredVoteData
    .Union(directoryAsVoteData, new VoteDataEqualityComparer())
    .ToList();

关键注意事项

  • 空值过滤规则:可以根据你的实际业务调整,比如是否允许某个字段为空,或者只要有一个邮箱字段不为空就算有效。
  • 重复判断逻辑:自定义比较器中的Equals方法可以按需修改——比如如果只要VoteFunction+Area+Sector相同就算重复,就去掉邮箱的判断条件。
  • 大小写敏感性:示例中用了StringComparison.OrdinalIgnoreCase忽略大小写,如果需要区分大小写,直接使用string.Equals(x, y)即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:02:17