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

发布于 2024-11-07 05:48:34 字数 76 浏览 0 评论 0原文

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

I'm looking for a performant way to add distinct items of a second ICollection to an existing one. I'm using .NET 4.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

有木有妳兜一样 2024-11-14 05:48:34

这应该可以做到:

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

This should do it:

list1.Union(list2).Distinct(aCustomComparer).ToList()
司马昭之心 2024-11-14 05:48:34

只要它们是 IEnumerable,您就可以使用首选 Linq 答案:

var union = firstCollection.Union(secondCollection);

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

As long as they're IEnumerable, you can use the go-to Linq answer:

var union = firstCollection.Union(secondCollection);

This will use the default equality comparison, which for most objects is referential equality. To change this, you can define an IEqualityComparer generic to the item type in your collection that will perform a more semantic comparison, and specify it as the second argument of the Union.

熟人话多 2024-11-14 05:48:34

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

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

Another way to add to your exisiting list would be:

list1.AddRange(list2.Distinct().Except(list1));
昇り龍 2024-11-14 05:48:34

对你的问题最直接的答案 - 因为你没有给出关于你作为输入或需要作为输出的 ICollection 的实际类型的详细信息,这是 KeithS 给出的,

var union = firstCollection.Union(secondCollection);

这将返回一个不同的 IEnumerable - 如果这就是你所需要的它非常快。我制作了一个小型测试应用程序(如下),该应用程序针对简单的重复数据删除哈希集方法运行联合方法(方法A)并返回哈希集<>(方法B)。 union 方法破坏哈希集:

方法A:1ms

方法B:2827ms

然而——必须将该 IEnumerable 转换为某种其他类型的集合,例如 List<> (就像 AD 发布的版本一样)改变了一切:

只需将 .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);
            }
        }
    }

The most direct answer to your question - since you didn't give much detail on the actual types of ICollection you have as input or need as output is the one given by KeithS

var union = firstCollection.Union(secondCollection);

This will return a distinct IEnumerable - if that is what you need then it is VERY fast. I made a small test app (below) that ran the union method (MethodA) against a simple hashset method of deduplicating and returns a Hashset<>(MethodB). The union method DESTROYS the hashset:

MethodA: 1ms

MethodB: 2827ms

However -- Having to convert that IEnumerable to some other type of collection such as List<> (like the version ADas posted) changes everything:

Simply adding .ToList() to MethodA

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

Changes the results:

MethodA: 3656ms

MethodB: 2803ms

So - it seems more would need to be known about the specific case you are working with - and any solution you come up with should be tested - since a small (code) change can have HUGE impacts.

Below is the test I used to compare these methods - I'm sure it is a stupid way to test - but it seems to work :)

    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);
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文