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

C#比对两个大型数组 获取新增元素对应位置标记数组的实现方案

数组差异标记C#实现方案

核心逻辑采用主流对比工具通用的Myers差分算法,匹配最长公共子序列后标记插入位置,可高效处理最大70万级别的数据量,效果和Beyond Compare一致。

由于你的场景中array2仅在array1基础上插入新元素、无删除/修改原有元素的操作,算法会自动定位array1所有元素在array2中的对应位置,其余位置标记为新增即可。


完整实现代码

using System;
using System.Collections.Generic;
using System.Linq;

public static class DiffHelper
{
    /// <summary>
    /// 生成array2的新增元素标记数组
    /// </summary>
    /// <param name="array1">原始数组</param>
    /// <param name="array2">插入新增元素后的数组</param>
    /// <returns>和array2长度一致的标记数组,0=匹配原始序列,1=新增元素</returns>
    public static int[] GenerateInsertMarkArray(byte[] array1, byte[] array2)
    {
        int n = array1.Length;
        int m = array2.Length;
        int[] result = Enumerable.Repeat(1, m).ToArray(); // 默认全部标1,匹配到的再改0
        
        // 计算编辑路径
        var path = MyersDiff(array1, array2);
        
        // 回溯路径标记匹配位置
        int x = n, y = m;
        foreach (var (dx, dy) in path.Reverse())
        {
            if (dx == 1 && dy == 1) // 匹配步,对应位置标0
            {
                result[y - 1] = 0;
            }
            x -= dx;
            y -= dy;
        }

        return result;
    }

    /// <summary>
    /// Myers差分算法核心实现,返回编辑路径
    /// </summary>
    private static List<(int dx, int dy)> MyersDiff(byte[] a, byte[] b)
    {
        int n = a.Length;
        int m = b.Length;
        int max = n + m;
        int[] v = new int[2 * max + 2];
        Array.Fill(v, -1);
        v[max + 1] = 0;
        
        // 存储每一步的v快照用于回溯
        var vs = new List<int[]>();
        
        int d;
        for (d = 0; d <= max; d++)
        {
            vs.Add((int[])v.Clone());
            for (int k = -d; k <= d; k += 2)
            {
                int x;
                if (k == -d || (k != d && v[max + k - 1] < v[max + k + 1]))
                {
                    x = v[max + k + 1];
                }
                else
                {
                    x = v[max + k - 1] + 1;
                }
                int y = x - k;
                
                while (x < n && y < m && a[x] == b[y])
                {
                    x++;
                    y++;
                }

                v[max + k] = x;
                if (x >= n && y >= m)
                {
                    // 回溯路径
                    var path = new List<(int dx, int dy)>();
                    for (int i = d; i >= 0; i--)
                    {
                        var prevV = vs[i];
                        int prevK = k;
                        if (k == -i || (k != i && prevV[max + k - 1] < prevV[max + k + 1]))
                        {
                            prevK = k + 1;
                        }
                        else
                        {
                            prevK = k - 1;
                        }

                        int prevX = prevV[max + prevK];
                        int prevY = prevX - prevK;
                        
                        // 添加匹配步
                        while (x > prevX && y > prevY && a[x-1] == b[y-1])
                        {
                            path.Add((1, 1));
                            x--;
                            y--;
                        }

                        if (i > 0)
                        {
                            path.Add(x - prevX, y - prevY);
                        }

                        x = prevX;
                        y = prevY;
                        k = prevK;
                    }

                    return path;
                }
            }
        }

        return new List<(int dx, int dy)>();
    }

    // 兼容int数组测试的重载
    public static int[] GenerateInsertMarkArray(int[] array1, int[] array2)
    {
        return GenerateInsertMarkArray(array1.Select(i => (byte)i).ToArray(), array2.Select(i => (byte)i).ToArray());
    }
}

用法示例

public static void Main()
{
    // 示例测试数据
    int[] array1 = {1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 0, 0, 0};
    int[] array2 = {1, 1, 1, 2, 7, 7, 2, 2, 2, 2, 1, 2, 3, 2, 2, 3, 3, 4, 7, 2, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 8, 4, 1, 1, 7, 7, 8, 8, 9, 9, 0, 0};

    int[] array3 = DiffHelper.GenerateInsertMarkArray(array1, array2);
    
    // 输出标记数组,和需求示例完全一致
    Console.WriteLine("array3: [{0}]", string.Join(", ", array3));
    
    // 获取所有新增元素的索引,对应Beyond Compare右侧红色标记位置
    List<int> insertIndexes = array3.Select((val, idx) => (val, idx))
                                    .Where(t => t.val == 1)
                                    .Select(t => t.idx)
                                    .ToList();
    Console.WriteLine("新增元素索引:[{0}]", string.Join(", ", insertIndexes));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:36:03