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

C#实现List对象按双属性关联关系连通分组的方法

实现方案

这个需求本质是无向图连通分量识别问题:每个提交字符串是图的节点,每条配对记录是连接两个节点的无向边,最终要把同属一个连通分量的所有边(配对记录)归为同一组。
最适合这个场景的实现是用并查集(Disjoint Set Union, DSU)结构,合并和查找连通关系的效率极高,代码逻辑也简单,不会出现多层遍历漏判关联关系的问题。


完整代码

1. 基础类定义

注意你给出的示例JSON属性名带尾随空格,反序列化时记得加特性映射,否则会拿不到属性值:

// 用System.Text.Json反序列化的话加下面的特性,用Newtonsoft.Json换[JsonProperty]即可
public class TopComparison
{
    [JsonPropertyName("first_submission ")]
    public string first_submission { get; set; }
    [JsonPropertyName("second_submission ")]
    public string second_submission { get; set; }
}

2. 并查集辅助类

public class UnionFind
{
    // 存储节点的父节点映射
    private readonly Dictionary<string, string> _parent = new();
    // 查找节点根节点,带路径压缩优化
    private string Find(string node)
    {
        if (!_parent.ContainsKey(node))
            _parent[node] = node;
        if (_parent[node] != node)
            _parent[node] = Find(_parent[node]);
        return _parent[node];
    }
    // 合并两个节点所在的连通集合
    public void Union(string nodeA, string nodeB)
    {
        string rootA = Find(nodeA);
        string rootB = Find(nodeB);
        if (rootA != rootB)
            _parent[rootB] = rootA;
    }
    // 获取节点所属连通分量的唯一标识(根节点)
    public string GetGroupKey(string node) => Find(node);
}

3. 分组逻辑实现

public List<List<TopComparison>> GroupTopComparisons(List<TopComparison> source)
{
    var uf = new UnionFind();
    // 第一遍遍历:合并所有关联节点
    foreach (var item in source)
    {
        // 跳过空值记录,避免抛异常
        if (string.IsNullOrWhiteSpace(item.first_submission) || string.IsNullOrWhiteSpace(item.second_submission))
            continue;
        uf.Union(item.first_submission, item.second_submission);
    }
    // 第二遍遍历:按连通分量分组
    var groupDict = new Dictionary<string, List<TopComparison>>();
    foreach (var item in source)
    {
        if (string.IsNullOrWhiteSpace(item.first_submission) || string.IsNullOrWhiteSpace(item.second_submission))
            continue;
        // 同一条记录的两个节点属于同一连通分量,取任意一个的分组key即可
        string groupKey = uf.GetGroupKey(item.first_submission);
        if (!groupDict.ContainsKey(groupKey))
            groupDict[groupKey] = new List<TopComparison>();
        groupDict[groupKey].Add(item);
    }
    // 转成需要的嵌套列表格式返回
    return groupDict.Values.ToList();
}

可选调整说明
  • 如果需要忽略大小写做关联匹配(比如示例里的harry和Harry判定为同一个键),只要把并查集中的字典初始化改成传入大小写不敏感的比较器即可:
    private readonly Dictionary<string, string> _parent = new(StringComparer.OrdinalIgnoreCase);
    
  • 该实现自动支持多层关联传递,比如A-B、B-C、C-D、D-E这类链式关联的记录,会全部被归到同一组,没有关联层数限制。
  • 传入测试数据集运行后,会得到和期望完全一致的3个分组结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:54:22