2011-05-13 81 views

回答

13

這應做到:

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

是不是多餘的使用distinct()在Union()之後? – 0xbadf00d

+2

取決於工會的條件。默認情況下,Union()方法只會對具有相同引用的對象進行重複數據刪除。由於Distinct使用自定義的IEqualityComparer,因此它實際上會做比聯合更多的事情。但是,IEqualityComparer也可以直接作爲聯盟使用,因此它有點多餘 – KeithS

+0

Union使用默認的相等比較器,根據類型的不同,它可能是也可能不是參考比較器。請參閱https://msdn.microsoft.com/en-us/library/vstudio/bb341731(v=vs.100).aspx和https://msdn.microsoft.com/en-us/library/vstudio/bb341731( v = VS.100)的.aspx。此外,正如你所提到的那樣,最好將自定義比較器提供給'Union'方法,並且爲了可讀性和(可能)略微提高性能而取消「Distinct」調用。 –

6

只要他們IEnumerable的,你可以使用去到Linq的答案:

var union = firstCollection.Union(secondCollection); 

這將使用默認的相等比較,這對於大多數對象來說是引用相等。爲了改變這種情況,您可以爲集合中的項目類型定義一個IEqualityComparer泛型,以執行更多的語義比較,並將其指定爲聯盟的第二個參數。

2

另一種方式添加到您的exisiting名單將是:

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

這基本上是Union(),BTW背後的操作。 Except()迭代器將基本上在傳遞的list1上調用Any(x => x == Current),並從list2返回它爲false的項目。 – KeithS

+0

除聯盟不修改原始列表外,OP要求'將第二個ICollection的不同項目添加到現有列表',聯盟返回一個新的集合。 –

+0

我的答案可能不是OP想要的,但是他的問題可能是模棱兩可的。 –

2

最直接的回答你的問題 - 因爲你沒有實際類型的ICollection的你必須爲輸入或需要提供多少細節作爲輸出是KeithS

var union = firstCollection.Union(secondCollection); 

給出的這將返回一個不同的IEnumerable - 如果這是你需要的話,就非常快。我製作了一個運行聯合方法(MethodA)的小測試應用程序(MethodA),該應用程序針對重複數據刪除的簡單哈希集方法,並返回一個Hashset(MethodB)。工會法破壞了HashSet的:

治法:1毫秒

方法b:2827ms

然而 - 有到了IEnumerable轉換爲其他類型的集合如List <>(如發佈版本ADAS)改變了一切:

簡單地增加.ToList()來治法

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

改變的結果:

治法: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); 
      } 
     } 
    } 
+0

只是要清楚;總是比Linq有更高性能的解決方案。然而,對於你在.NET中開始編程的99.9%(與更多的本地語言相比,它會將任何.NET實現排除在外),Linq在性能方面表現良好,並且通常更易於理解和執行。 – KeithS

+0

MethodA更快的原因是因爲它沒有枚舉它返回的集合的元素,這就是調用ToList的原因使它慢得多。 –