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

时间:2011-05-13 14:48:30

标签: c# collections

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

4 个答案:

答案 0 :(得分:13)

这应该这样做:

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

答案 1 :(得分:6)

只要它们是IEnumerable,你就可以使用Linq的回答:

var union = firstCollection.Union(secondCollection);

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

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

var union = firstCollection.Union(secondCollection);

这将返回一个独特的IEnumerable - 如果这是你需要的那么它非常快。我做了一个小测试应用程序(下面),它针对重复数据删除的简单hashset方法运行union方法(MethodA)并返回一个Hashset<>(MethodB)。联合方法DESTROYS hashset:

  

方法A:1毫秒

     

方法B:2827ms

但是 - 必须将IEnumerable转换为其他类型的集合,例如List<> (就像ADas发布的版本一样)改变了一切:

只需将.ToList()添加到MethodA

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

更改结果:

  

方法A:3656ms

     

方法B:2803毫秒

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

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

    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);
            }
        }
    }