2012-03-09 10 views
12

कहें कि मैं यह जांचना चाहता हूं कि संग्रह में कम से कम एन तत्व हैं या नहीं।LINQ गणना() तक, यह और अधिक कुशल है?

क्या यह करने से बेहतर है?

Count() >= N

का उपयोग करना:

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

या यहां तक ​​कि

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

कैसे कर सकता था मैं बेंचमार्क है?

/// <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 मैं बेंचमार्क सकता है इस _ - कोड आप सामान्य रूप से उन्हें समय के साथ एक पाश में आह्वान करने के लिए प्रयोग करेंगे रखो ..? –

+0

दूसरा विकल्प: गणनीय। चयन करें ((ओ, idx) => idx)। कोई (i => i> = max); – KristoferA

उत्तर

5

कुछ अच्छी तरह से प्रलेखित .Count() विधि करने के लिए बनाया अनुकूलन कर रहे हैं। विशेष रूप से, यदि आपका गणनीय ICollection है, .Count() एक स्थिर समय ऑपरेशन होगा क्योंकि यह ICollection की .Count संपत्ति का उपयोग करेगा।

हालांकि, सामान्य स्थिति में यह गिनती प्राप्त करने के लिए पूरे IEnumerable को फिर से चालू करेगा। यदि आपके पास ICollection नहीं है, तो एन तत्वों से अधिक होने पर आप अपने दो सुझाए गए तरीकों का उपयोग करके बेहतर हो जाएंगे। उन दोनों के सापेक्ष प्रदर्शन के लिए, आपको उन्हें प्रोफाइल करना होगा क्योंकि अन्य ने सुझाव दिया है।

+0

मैं उनके कार्यान्वयन के बारे में सावधान रहूंगा। क्या हम गारंटी देते हैं कि किसी भी लिंकक विधियों को बाहरी चर में लिखने के साथ थ्रेड सुरक्षित किया जाएगा? यदि यह 'IENumerable ' अनुक्रमिक रूप से ट्रैवर करता है तो यह ठीक होना चाहिए। लेकिन अगर किसी भी समय समानांतर में मूल्यांकन करने वाले कई धागे हो सकते हैं, तो यह बीमार परिभाषित हो सकता है। –

+0

@ माइक: कम से कम मुझे लगता है कि 'टेक (एन)' दृष्टिकोण ठीक रहेगा - आखिरकार, यह केवल 'एन' तत्वों तक पहुंचने के बाद गणित को रोक रहा है और पूरे संग्रह को फिर से चालू किया गया है (यदि 'IENumerable' में 'n' तत्वों से कम हैं)। मुझे 'एनी()' दृष्टिकोण की धागा सुरक्षा के बारे में निश्चित नहीं है। – 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); 

परिणाम जहां PrintTime() टाइमर बाहर प्रिंट टिक्स:

True 20818 
True 8774 
True 8688 
+1

यह एक ऐसी सूची का उपयोग करके समझ में नहीं आता है, जिसे आप जानते हैं कि 'गणना' 100000 है, और किसी भी तरीके का आह्वान करने की आवश्यकता नहीं है। सूची के बिना, केवल enumerable.range का उपयोग करने के साथ आपके resulsts क्या हैं? – bevacqua

+0

निको, अच्छा बिंदु :) केवल अंकुरित। श्रेणी का उपयोग करके परिणामों को प्रतिबिंबित करने के लिए अद्यतन उत्तर। वास्तविक समय देने के लिए – Beyers

+0

+1। – jwg

संबंधित मुद्दे