2012-03-09 17 views
12

Giả sử tôi muốn kiểm tra xem có ít nhất N phần tử trong bộ sưu tập hay không.LINQ Count() cho đến khi, điều này có hiệu quả hơn không?

Điều này có tốt hơn là làm không?

Count() >= N

Sử dụng:

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

Hoặc thậm chí

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

Làm thế nào có thể tôi chuẩn này?

/// <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 thể tôi chuẩn này _ - Đặt mã bạn thường sử dụng để gọi chúng trong một vòng lặp với thời gian ..? –

+0

một tùy chọn khác: enumerable.Select ((o, idx) => idx). Bất kỳ (i => i> = max); – KristoferA

Trả lời

5

Có một số tối ưu hóa tài liệu được xây dựng theo phương pháp .Count(). Cụ thể, nếu số đếm của bạn là ICollection, .Count() sẽ là hoạt động không đổi theo thời gian vì nó sẽ sử dụng thuộc tính ICollection 's .Count.

Tuy nhiên, trong trường hợp chung, nó sẽ lặp lại toàn bộ số IEnumerable để nhận số. Nếu bạn không có ICollection, bạn nên sử dụng một trong hai phương pháp được đề xuất của mình khi có nhiều hơn N phần tử. Đối với hiệu suất tương đối của hai, bạn sẽ phải hồ sơ chúng như những người khác đã đề xuất.

+0

Tôi sẽ cảnh giác về việc triển khai của anh ta. Chúng tôi có đảm bảo rằng bất kỳ phương pháp nào của Linq sẽ là luồng an toàn bằng cách viết vào một biến bên ngoài như vậy không? Nếu nó đi qua 'IEnumerable ' tuần tự nó sẽ được sử dụng tốt. Nhưng nếu bất cứ lúc nào nó có thể có nhiều chủ đề đánh giá rằng song song, có thể bị bệnh xác định. –

+0

@Mike: Tối thiểu tôi nghĩ phương pháp '.Take (n)' sẽ ổn - sau khi tất cả, nó chỉ lặp đi lặp lại đếm và dừng sau khi các phần tử 'n' đã đạt tới hoặc toàn bộ bộ sưu tập đã được lặp lại (nếu có ít hơn 'n' phần tử trong' IEnumerable'). Tôi không chắc về an toàn luồng của phương thức '.Any()'. – 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); 

Kết quả nơi PrintTime() in ra timer ticks:

True 20818 
True 8774 
True 8688 
+1

điều này thậm chí không có ý nghĩa, bằng cách sử dụng một danh sách bạn biết cho một thực tế là 'Count' là 100000, và không cần phải gọi bất kỳ phương pháp. Bạn có thể sử dụng danh sách enumerable.range mà không có danh sách? – bevacqua

+0

Nico, điểm tốt :) Cập nhật câu trả lời để phản ánh kết quả chỉ bằng Enumerable.Range. – Beyers

+0

+1 để cung cấp thời gian thực tế. – jwg