2010-06-16 13 views
9

के सदस्य के लिए ऑर्डर बी(), मैंने खुद को कुछ पुराने 3.5 फ्रेमवर्क विरासत कोड के माध्यम से वापस चला पाया है, और कुछ बिंदुएं हैं जहां पूरी तरह से हैं सूचियों और शब्दकोशों का समूह जो सिंक्रनाइज़ फैशन में अपडेट किया जाना चाहिए। मैंने यह निर्धारित किया है कि मैं इन प्रक्रियाओं को नए कस्टम वर्गों के कस्टम कंटेनर कक्षाओं में परिवर्तित करके उपयोग और समझने के लिए असीम रूप से आसान बना सकता हूं। कुछ बिंदु हैं, हालांकि, जहां मैं इन नए कंटेनर कक्षाओं की सामग्री को एक विशिष्ट आंतरिक संपत्ति द्वारा व्यवस्थित करने के साथ चिंताओं पर आया था। उदाहरण के लिए, एक वर्ग की आईडी संख्या संपत्ति द्वारा सॉर्ट करना।सूची की उपयोगिता <T> .Sort() बनाम सूची <T>। कस्टमर कंटेनर क्लास

कंटेनर कक्षाएं मुख्य रूप से एक सामान्य सूची वस्तु के आधार पर आधारित होती हैं, मेरी पहली प्रवृत्ति आईसीओम्पेर्बल के साथ आंतरिक कक्षाएं लिखना था, और गुणों की तुलना करने वाली तुलनात्मक विधि लिखना था। इस तरह, मैं सॉर्टिंग का आह्वान करना चाहता हूं, तो बस items.Sort() पर कॉल कर सकता हूं।

हालांकि, मैं इसके बजाय items = items.OrderBy(Func) का उपयोग करने के बारे में सोच रहा हूं। अगर मुझे किसी अन्य संपत्ति द्वारा सॉर्ट करने की ज़रूरत है तो इस तरह यह अधिक लचीला है। पठनीयता भी बेहतर है, क्योंकि सॉर्टिंग के लिए उपयोग की जाने वाली संपत्ति को आईसीओपरपेरबल कोड को देखने के बजाय सॉर्ट कॉल के साथ ऑनलाइन सूचीबद्ध किया जाएगा। परिणामस्वरूप समग्र कार्यान्वयन क्लीनर महसूस करता है।

मुझे समयपूर्व या सूक्ष्म अनुकूलन की परवाह नहीं है, लेकिन मुझे स्थिरता पसंद है। मुझे उचित रूप से कई मामलों के लिए एक तरह के कार्यान्वयन के साथ चिपकना सबसे अच्छा लगता है, और यह आवश्यक है कि विभिन्न कार्यान्वयन का उपयोग करें। List.Sort का उपयोग करने के बजाय LINQ ऑर्डरबी का उपयोग करने के लिए मेरे कोड को परिवर्तित करना उचित है? क्या इन कस्टम कंटेनरों के लिए आईसीओम्परेबल कार्यान्वयन के साथ चिपकने का यह बेहतर अभ्यास है? क्या किसी भी पथ द्वारा प्रस्तावित कोई महत्वपूर्ण यांत्रिक लाभ है कि मुझे निर्णय का वजन करना चाहिए? या उनकी अंतिम कार्यक्षमता इस बिंदु के बराबर है कि यह सिर्फ कोडर की वरीयता बन जाती है?

उत्तर

18

यहां प्रमुख बात यह है कि List<T>.Sort() जगह में सॉर्टिंग करता है। यदि आपकी सूची बाहरी कोड से अवगत कराई गई है, तो यह हमेशा इस कोड पर एक ही ऑब्जेक्ट का प्रतिनिधित्व करेगी। यह महत्वपूर्ण है अगर सूची को कंटेनर क्लास के बाहर कोड द्वारा फ़ील्ड में रखा जाता है। यदि आप OrderBy() के साथ सॉर्ट कर रहे हैं, तो आपको पिछले items को प्रतिस्थापित करने पर हर बार एक नया गणना मिलेगी। कोई भी पहले संग्रहीत सूची आपकी कक्षा की वर्तमान स्थिति का प्रतिनिधित्व नहीं करेगी।

प्रदर्शन को ध्यान में रखते हुए, OrderBy आइटम को सॉर्ट करने के लिए पूरी सूची के माध्यम से फिर से शुरू करना होगा। फिर आप इस गणना से नई सूची बनाने के लिए ToList() पर कॉल करेंगे, दूसरी बार सूची के माध्यम से पुनरावृत्त करेंगे। इसके अलावा, चूंकि यह एक गणना है, सूची दोगुनी एल्गोरिदम का उपयोग करेगी, इसके आकार को तब तक बढ़ाएगी जब तक कि प्रत्येक तत्व इसमें फिट न हो। बड़ी सूची के मामले में, यह कुछ आवंटन और स्मृति प्रतिलिपि हो सकता है। मैं उम्मीद करता हूं कि प्रदर्शन List<T>.Sort() से भी बदतर होगा।

संपादित करें: छोटे बेंचमार्क:

internal class Program { 

    private static List<int> CreateList(int size) { 

     // use the same seed so that every list has the same elements 
     Random random = new Random(589134554); 

     List<int> list = new List<int>(size); 
     for (int i = 0; i < size; ++i) 
      list.Add(random.Next()); 
     return list; 
    } 

    private static void Benchmark(int size, bool output = true) { 
     List<int> list1 = CreateList(size); 
     List<int> list2 = CreateList(size); 

     Stopwatch stopwatch = Stopwatch.StartNew(); 
     list1.Sort(); 
     stopwatch.Stop(); 
     double elapsedSort = stopwatch.Elapsed.TotalMilliseconds; 
     if (output) 
      Console.WriteLine("List({0}).Sort(): {1}ms (100%)", size, elapsedSort); 

     stopwatch.Restart(); 
     list2.OrderBy(i => i).ToList(); 
     stopwatch.Stop(); 
     double elapsedOrderBy = stopwatch.Elapsed.TotalMilliseconds; 
     if (output) 
      Console.WriteLine("List({0}).OrderBy(): {1}ms ({2:.00%})", size, elapsedOrderBy, elapsedOrderBy/elapsedSort); 

    } 

    internal static void Main() { 

     // ensure linq library is loaded and initialized 
     Benchmark(1000, false); 

     Benchmark(10); 
     Benchmark(100); 
     Benchmark(1000); 
     Benchmark(10000); 
     Benchmark(100000); 
     Benchmark(1000000); 

     Console.ReadKey(); 
    } 
} 

आउटपुट (List.Sort को सामान्यीकृत):

List(10).Sort(): 0,0025ms (100%) 
List(10).OrderBy(): 0,0157ms (628,00%) 
List(100).Sort(): 0,0068ms (100%) 
List(100).OrderBy(): 0,0294ms (432,35%) 
List(1000).Sort(): 0,0758ms (100%) 
List(1000).OrderBy(): 0,3107ms (409,89%) 
List(10000).Sort(): 0,8969ms (100%) 
List(10000).OrderBy(): 4,0751ms (454,35%) 
List(100000).Sort(): 10,8541ms (100%) 
List(100000).OrderBy(): 50,3497ms (463,88%) 
List(1000000).Sort(): 124,1001ms (100%) 
List(1000000).OrderBy(): 705,0707ms (568,15%) 
+0

ठीक है, आपके मानक द्वारा संकेतित मात्रा बोलती है ... वॉल्यूम्स।इस तरह की दरों पर, मैं उस बिंदु को प्रतिस्थापित करने के लिए 3 प्रकारों में निचोड़ भी कर सकता हूं, मैंने 3 ऑर्डरबिज का इस्तेमाल किया था, और बेहतर प्रदर्शन प्राप्त किया था अगर मैंने केवल एक ऑर्डरबी का उपयोग किया था! क्रमबद्ध करें() यह है! –

+0

आपकी त्वरित गणना के आधार पर एक त्वरित अनुवर्ती ... क्या इसका यह भी अर्थ होगा कि 'आइटम। पहला() 'आइटम [0]' से काफी धीमा है? –

+0

नहीं, 'प्रथम() '' IList 'कार्यान्वयन के लिए अनुकूलित किया गया है और' सूची [0]' वापस कर देगा। मुझे उम्मीद है कि प्रदर्शन समान होगा। यहां तक ​​कि अगर यह सीधे गणना का उपयोग कर रहा था, फिर भी यह फिर से एक आइटम होगा फिर भी यह एक माइक्रो अनुकूलन होगा। –

4

के रूप में जुलिएन ने कहा, क्रमबद्ध() शायद जब से तुम उल्लेख किया है, तेजी से हो जाएगा तथापि ऑर्डरबी() की बेहतर पठनीयता और लचीलापन, आप इसे अपने सॉर्ट() विधि के साथ भी प्राप्त कर सकते हैं (कम से कम अगर आप जिस संपत्ति को अपने आधार पर आधार बनाना चाहते हैं वह तुलनीय है)

items = items.OrderBy(x => x.Name).ToList(); 
items.Sort((x,y) => x.Name.CompareTo(y.Name)); // If x.Name is never null 
items.Sort((x,y) => String.Compare(x.Name, y.Name)); // null safe 
+0

इन दिनों में से एक, मैं अतिरिक्त छोटी चीजों को भूलना बंद कर दूंगा जैसे "मैं IComparable पर भरोसा करने के बजाय सॉर्ट फ़ंक्शन निर्दिष्ट कर सकता हूं"। जो महान है, क्योंकि इससे मुझे कुछ वर्गों को "तुलनीय" होने के रूप में निर्दिष्ट करने से बचने की अनुमति मिलती है जब उन्हें वास्तव में ऐसा महसूस नहीं होता है, तो उन्हें कुछ स्थितियों में हल करने की आवश्यकता होती है। मैंने अपनी सफलता को पूरा करने के लिए जूलियन के डेटा के साथ अपना जवाब जोड़ दिया है। बहुत धन्यवाद! –

+0

मैं IComparer को IComparable पसंद करते हैं। इस तरह आप एल्गोरिदम सॉर्ट करने के विभिन्न encapsulations के आसपास पारित कर सकते हैं। –

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