2012-03-09 17 views
12

Koleksiyonda en az N öğesi olup olmadığını kontrol etmek istiyorum.LINQ Count() şu tarihe kadar, daha verimli mi?

Bunu yapmaktan daha mı iyi?

Count() >= N

kullanma:

public static bool AtLeast<T>(this IEnumerable<T> enumerable, int max) 
    { 
     int count = 0; 
     return enumerable.Any(item => ++count >= max); 
    } 

Hatta

public static bool Equals<T>(this IEnumerable<T> enumerable, int amount) 
    { 
     return enumerable.Take(amount).Count() == amount; 
    } 

nasıl kriter bu ki?

/// <summary> 
    /// Returns whether the enumerable has at least the provided amount of elements. 
    /// </summary> 
    public static bool HasAtLeast<T>(this IEnumerable<T> enumerable, int amount) 
    { 
     return enumerable.Take(amount).Count() == amount; 
    } 

    /// <summary> 
    /// Returns whether the enumerable has at most the provided amount of elements. 
    /// </summary> 
    public static bool HasAtMost<T>(this IEnumerable<T> enumerable, int amount) 
    { 
     return enumerable.Take(amount + 1).Count() <= amount; 
    } 
+3

_How kriter yapabilirdim bu _ - normalde zamanlama ile bir döngü içinde onları çağırmak için kullandığımız kod yerleştirin ..? –

+0

başka bir seçenek: enumerable.Select ((o, idx) => idx) .Ay (i => i> = max); – KristoferA

cevap

5

.Count() yönteme yerleşik bazı iyi belgelenmiş optimizasyonlar vardır. Özellikle, numaranız ICollection ise, .Count(), ICollection 'un .Count özelliğini kullanacağı için sabit zamanlı bir işlem olacaktır. Bununla birlikte, genel durumda sayımı almak için genel olarak IEnumerable'un tamamını yineleyecektir. Bir ICollection yoksa, N'den fazla öğe olduğunda önerilen iki yöntemden birini kullanarak daha iyi durumda olursunuz. Bu ikisinin göreceli performansı için, başkalarının önerdiği gibi onları izlemelisiniz. PrintTime() zamanlayıcı yazdırır

+0

Onun uygulamaları hakkında ihtiyatlı olacağım. Herhangi bir Linq yönteminin böyle bir dış değişkene yazı yazarak iş parçacığı güvenli olacağını garanti ediyoruz? IEnumerable 'dizisini geçerse, bu işlem düzgün olmalıdır. Ancak, herhangi bir zamanda, paralel olarak değerlendiren birden fazla parçacığa sahip olmak olasıysa, bu hastalanmış olabilir. –

+0

@Mike: En azından '.Take (n)' yaklaşımının iyi olacağını düşünürdüm - sonuçta 'n' öğelerine ulaşıldıktan veya tüm koleksiyonun yinelendikten sonra numaralandırılabilir ve durdurulamıyor (IEnumerable'da 'n' öğelerinden daha az varsa. '.Any()' yaklaşımının iplik güvenliği konusunda emin değilim. – goric

2
 var list = Enumerable.Range(1, 1000000); 
     var t = new Stopwatch(); 

     t.Restart(); 
     var count = list.Count() > 100000; 
     t.Stop(); 
     PrintTime(t, count); 

     t.Restart(); 
     var atLeast = list.AtLeast(100000); 
     t.Stop(); 
     PrintTime(t, atLeast); 

     t.Restart(); 
     var equals = list.Equalss(100000); 
     t.Stop(); 
     PrintTime(t, equals); 

Sonuçlar keneler:

True 20818 
True 8774 
True 8688 
+1

bu, 'Count' 100000 olduğunu ve herhangi bir yöntemi çağırmaya gerek duymadığını bildiğiniz bir listeyi kullanarak anlam ifade etmiyor. Listeniz olmadan sadece enumerable.range kullanarak sonuçlarınız nelerdir? – bevacqua

+0

Nico, iyi nokta :) Sadece Enumerable.Range kullanarak sonuçları yansıtacak şekilde güncellendi. Gerçek zamanlamaları vermek için – Beyers

+0

+1. – jwg