2011-05-13 21 views

cevap

13

kullanıyorum:

var union = firstCollection.Union(secondCollection); 

Bu:

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

görünüyor o Farklı kullanmak gereksiz() Union'dan sonra()? – 0xbadf00d

+2

Birliğin koşullarına göre değişir. Varsayılan olarak, Union() yöntemi yalnızca aynı referansta bulunan nesneleri çıkarır. Distinct özel bir IEqualityComparer kullandığı için, aslında sendikadan daha fazlasını yapacak.ANCAK, IEqualityComparer'ın aynı zamanda doğrudan birleşik olarak kullanımı için de verilebilir, bu yüzden biraz fazlalık olan – KeithS

+0

'Union', türüne bağlı olarak, bir karşılaştırma karşılaştırıcısı olabilir veya olmayabilir, varsayılan eşitlik karşılaştırıcısı kullanır. Https://msdn.microsoft.com/en-us/library/vstudio/bb341731(v=vs.100).aspx ve https://msdn.microsoft.com/en-us/library/vstudio/bb341731 adresine bakın. v = vs.100) .aspx. Dahası, bahsettiğiniz gibi, özel karşılaştırmayı “Birlik” yöntemine sunmak ve okunabilirlik için “Farklı” çağrıyı ve (belki?) Hafif bir performans artışı elde etmek daha iyidir. –

6

Yeter ki IEnumerable konum olarak alacak-to Linq cevap kullanabilirsiniz Çoğu nesne için referans eşitliği olan varsayılan eşitlik karşılaştırmasını kullanır. Bunu değiştirmek için, daha çok anlamsal bir karşılaştırma yapacak ve bunu Birliğin ikinci argümanı olarak belirleyecek olan koleksiyonunuzdaki öğe türüne bir IEqualityComparer jenerik tanımlayabilirsiniz.

2

bir başka yolu olacağını sizin Mevcut bir listenize eklemek için:

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

Temel olarak bu, Union(), BTW'nin arkasındaki işlemdir. Except() yineleyicisi, geçirilen listeye temelde Any (x => x == Current) öğesini çağırır ve item2'den false olduğu öğeleri döndürür. – KeithS

+0

Birlik hariç, orijinal listeyi değiştirmeyen OP, 'varolan bir tanesine ikinci bir İcolasyon'un farklı öğelerini ekleme' talebinde bulundu, Union yeni bir koleksiyon döndürdü. –

+0

Cevabım, OP'nin istediği gibi olmayabilir, ama onun sorusu yeterince belirsiz. –

2

Sorunuzun en direkt cevap - Eğer giriş ya da ihtiyaç olarak sahip ICollection gerçek türlerinde çok ayrıntı vermediler beri çıktı Keiths

var union = firstCollection.Union(secondCollection); 

tarafından verilen biri olarak bu ayrı bir IEnumerable dönecektir - yani bunu çok hızlı sonra ne gerek olup olmadığını. Basit bir karma yöntemini tekilleştirme yöntemine karşı birleştirme yöntemini (MethodA) çalıştıran ve bir Hashset <> (YöntemB) döndüren küçük bir test uygulaması (aşağıda) yaptım. Böyle List <> olarak koleksiyonun diğer türde bazı o IEnumerable dönüştürmek zorunda (gibi -

Ancak 2827ms:

Yöntemia: 1 ms

MethodB birliği yöntemi HashSet YOK EDER versiyon Adas yayınlanmıştır) değiştirir her şeyi:

Basitçe Yöntemia

için .ToList() ekleyerek
var union = firstCollection.Union(secondCollection).ToList(); 
0 o Çalıştığınız belirli dosyayla ilgili bilinmesi gerekir fazla görünüyor - -

Yani 2803ms ve herhangi:

Yöntemia: 3656ms

MethodB

sonuçlarını değiştirir Bulunduğunuz çözüm test edilmelidir - küçük (kod) bir değişikliğin BÜYÜK etkileri olabilir. Ben test etmek için aptal yoludur eminim - - Aşağıda

Ben bu yöntemleri karşılaştırmak için kullanılan bir testtir değil mi ama çalışmak :)

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

Sadece açık olmak gerekirse; Linq'den daha performanslı bir çözüm var. Bununla birlikte, .NET'te programladığınız programın% 99,9'u (sudan herhangi bir .NET uygulamasına neden olacak daha anadili bir dilin aksine) Linq performansa ve genellikle daha okunaklı ve anlaşılabilir bir uygulamaya sahiptir. . – KeithS

+0

MethodA'nın çok daha hızlı olmasının sebebi, topladığı koleksiyonun elemanlarını saymadığı için, bu nedenle ToList'i çağırmanın bu kadar yavaş olmasının sebebi de budur. –

İlgili konular