C# 合并 2 个集合的不同项

本文关键字:集合 合并 | 更新日期: 2023-09-27 17:56:26

我正在寻找一种高性能的方式来将第二个 ICollection 的不同项目添加到现有项目。我正在使用 .NET 4。

C# 合并 2 个集合的不同项

这应该可以做到:

list1.Union(list2).Distinct(aCustomComparer).ToList()

只要它们是 IEnumerable,您就可以使用 go-to Linq 答案:

var union = firstCollection.Union(secondCollection);

这将使用默认的相等比较,对于大多数对象,这是参照相等。若要更改此设置,可以为集合中的项类型定义一个 IEqualityComparer 泛型,该泛型将执行更语义的比较,并将其指定为联合的第二个参数。

添加到现有列表中的另一种方法是:

list1.AddRange(list2.Distinct().Except(list1));

对你的问题最直接的答案 - 因为你没有给出太多关于你作为输入或需要作为输出的实际ICollection类型的细节,所以KeithS给出的答案是KeithS给出的

答案。
var union = firstCollection.Union(secondCollection);

这将返回一个不同的 IEnumerable - 如果这是你需要的,那么它非常快。 我制作了一个小型测试应用程序(下图),它针对一个简单的重复数据删除哈希集方法运行联合方法(MethodA),并返回一个Hashset<>(MethodB)。 联合方法销毁哈希集:

方法A:1ms

方法B:2827ms

但是 - 必须将该IEnumerable转换为其他类型的集合,例如List<>(如ADas发布的版本)会更改所有内容:

只需添加 .ToList() 到 MethodA

var union = firstCollection.Union(secondCollection).ToList();

更改结果:

方法A:3656ms

方法B:2803ms

所以 - 似乎需要更多地了解您正在使用的特定案例 - 并且您提出的任何解决方案都应该进行测试 - 因为一个小的(代码)更改可能会产生巨大的影响。

以下是我用来比较这些方法的测试 - 我确信这是一种愚蠢的测试方法 - 但它似乎有效:)

    private static void Main(string[] args)
    {
        ICollection<string> collectionA = new List<string>();
        ICollection<string> collectionB = new List<string>();
        for (int i = 0; i < 1000; i++)
        {
            string randomString = Path.GetRandomFileName();
            collectionA.Add(randomString);
            collectionA.Add(randomString);
            collectionB.Add(randomString);
            collectionB.Add(randomString);
        }
        Stopwatch testA = new Stopwatch();
        testA.Start();
        MethodA(collectionA, collectionB);
        testA.Stop();

        Stopwatch testB = new Stopwatch();
        testB.Start();
        MethodB(collectionA, collectionB);
        testB.Stop();
        Console.WriteLine("MethodA: {0}ms", testA.ElapsedMilliseconds);
        Console.WriteLine("MethodB: {0}ms", testB.ElapsedMilliseconds);
        Console.ReadLine();
    }
    private static void MethodA(ICollection<string> collectionA, ICollection<string> collectionB)
    {
        for (int i = 0; i < 10000; i++)
        {
            var result = collectionA.Union(collectionB);
        }
    }
    private static void MethodB(ICollection<string> collectionA, ICollection<string> collectionB)
    {
        for (int i = 0; i < 10000; i++)
        {
            var result = new HashSet<string>(collectionA);
            foreach (string s in collectionB)
            {
                result.Add(s);
            }
        }
    }