2009-08-05 18 views
12

लागू करने के लिए कैसे मैं अभ्यास के लिए कुछ विभिन्न एल्गोरिथम को लागू करना चाहते हैं, बस देखने के लिए कितना बुरा मैं वास्तव में हूँ और बेहतर हो: pसी #: IOrderedEnumerable <T>

फिर भी, मैंने सोचा कि मैं IEnumerable<T> और IOrderedEnumerable<T> का उपयोग करने की कोशिश करेंगे और अन्य .NET संग्रह प्रकार केवल संगत होने के लिए (ताकि जो मैं लिखूं वह बाद में अधिक आसानी से उपयोग किया जा सकता है)।

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

मैंने एक खाली कक्षा बनाई, इंटरफेस जोड़ा और फिर मेरे लिए खाली कार्यान्वयन जोड़ने के लिए रीशेपर मिला। यह इस तरह दिखता है:

class MyOrderedEnumerable<T> : IOrderedEnumerable<T> 
{ 
    /// <summary> 
    /// Performs a subsequent ordering on the elements of an <see cref="T:System.Linq.IOrderedEnumerable`1"/> according to a key. 
    /// </summary> 
    /// <returns> 
    /// An <see cref="T:System.Linq.IOrderedEnumerable`1"/> whose elements are sorted according to a key. 
    /// </returns> 
    /// <param name="keySelector">The <see cref="T:System.Func`2"/> used to extract the key for each element.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IComparer`1"/> used to compare keys for placement in the returned sequence.</param><param name="descending">true to sort the elements in descending order; false to sort the elements in ascending order.</param><typeparam name="TKey">The type of the key produced by <paramref name="keySelector"/>.</typeparam><filterpriority>2</filterpriority> 
    public IOrderedEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending) 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// Returns an enumerator that iterates through the collection. 
    /// </summary> 
    /// <returns> 
    /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection. 
    /// </returns> 
    /// <filterpriority>1</filterpriority> 
    public IEnumerator<T> GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// Returns an enumerator that iterates through a collection. 
    /// </summary> 
    /// <returns> 
    /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection. 
    /// </returns> 
    /// <filterpriority>2</filterpriority> 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

क्या मुझे समझ नहीं आता CreateOrderedEnumerable तरीका है। इसका क्या मतलब है? खैर, मुझे लगता है कि यह निश्चित रूप से एक आदेश दिया गया गणना करेगा, लेकिन कैसे? क्या सॉर्टिंग एल्गोरिदम स्वयं वहां जाना चाहता है? और यह क्या होगा? उस विधि में जाने वाली वस्तुओं का कोई संग्रह नहीं है, इसलिए संग्रह को ऑर्डर करने का मतलब कहां है? आप कक्षा का उपयोग कैसे करेंगे? क्या इसका मतलब यह है कि उदाहरण के लिए एक निजी सहायक वर्ग जो कुछ सामानों को हल करने की ज़रूरत है?

तो बजाय एक MyOrderedEnumerable<T> : IOrderedEnumerable<T> के लिए, आप एक QuickSorter<T> : IOrderedEnumerable<T> है कि इसके निर्माता में एक संग्रह ले लिया और यह हल कर जब कि CreateOrderedEnumerable विधि बुलाया गया था ... लेकिन क्या तब क्या होगा अगर किसी को GetEnumerator कहा जाता है और उस विधि से पहले की गणना करने में शुरू कर दिया हो सकता है कहा गया था?


Haha, बस की खोज की मैं ऐसी ही कुछ कहा था थोड़ी देर पहले here। लेकिन यह सिर्फ इतना था कि एक को वापस करना संभव था। तो मुझे लगता है कि यह प्रश्न मुझे मिला एक जवाब का जवाब है =)

उत्तर

11

मेरे पास sample implementation है जो आप देख सकते हैं। यह किसी भी माध्यम से कुशल होने के लिए डिज़ाइन नहीं किया गया है, लेकिन इसे शुरू करना चाहिए।

असल में IOrderedEnumerable<T> को केवल अपने वर्तमान ऑर्डरिंग का विचार होना चाहिए, इसलिए यह एक नया बना सकता है। यह मानते हुए की तरह कुछ कह कर आप पहले से ही एक IComparer<T> आप एक नया एक का निर्माण किया है:

int Compare(T first, T second) 
{ 
    if (baseComparer != null) 
    { 
     int baseResult = baseComparer.Compare(first, second); 
     if (baseResult != 0) 
     { 
      return baseResult; 
     } 
    } 
    TKey firstKey = keySelector(first); 
    TKey secondKey = keySelector(second); 

    return comparer.Compare(firstKey, secondKey);   
} 

तो मूल रूप से आप से "कम से कम महत्वपूर्ण" "सबसे महत्वपूर्ण" अप करने के लिए जा रहा comparers की एक श्रृंखला पैदा करते हैं। तुम भी डाल करने के लिए "उतरते" वहाँ में बिट की जरूरत है, लेकिन यह आसान MiscUtil में पहले से ही मौजूद है :)

नमूना ऊपर लिंक में, तीन अलग-अलग पहलू तीन अलग-अलग कक्षाओं में प्रतिनिधित्व कर रहे हैं:

  • ReverseComparer :, कुंजी करने के लिए मूल आइटम से एक प्रक्षेपण के आधार पर एक comparer बनाता है सौंपने: पराजयों एक मौजूदा 'IComparer<T> s परिणाम
  • LinkedComparer: दो से एक comparer बनाता है, एक गुरु और एक गुलाम
  • ProjectionComparer साथ उन चाबियों की तुलना करने के लिए एक और तुलनात्मक।

तुलनाकर्ता इस तरह एक साथ चेन करने के लिए महान हैं।

+0

मीठे! इसे एक बार में जांच लें =) – Svish

+0

तो यह आपके द्वारा दिए गए नए तुलनाकर्ता के आधार पर खुद को पुन: व्यवस्थित करेगा? या? यकीन नहीं है कि अगर मैं समझ गया कि ... – Svish

+0

यह खुद को पुन: व्यवस्थित नहीं करेगा - यह पुराने क्रम और नई तुलना के आधार पर नए आदेश के साथ एक नया अनुक्रम बनाएगा। यह मूल अनियंत्रित डेटा को प्राप्त करने के अलावा पुराने अनुक्रम का उपयोग नहीं करेगा। अधिक जानकारी के लिए कोड देखें :) –

1

संभवतः, आपकी कक्षा में कुछ आंतरिक स्टोरेज वैरिएबल होगा जो उदाहरण के लिए IEnumerable (List<T> लागू करता है)। इस विधि का कार्यान्वयन इस तरह के मामले में सरल है:

private List<T> data = new List<T>(); 

public IOrderedEnumerable<CalculationResult> CreateOrderedEnumerable<TKey>(Func<CalculationResult, TKey> keySelector, IComparer<TKey> comparer, bool descending) 
{ 
    return descending ? 
     data.OrderByDescending(keySelector, comparer) 
    : data.OrderBy(keySelector, comparer); 
} 
+0

यह गलत है। CreateOrderedEumerable को "ThenBy" LINQ फ़ंक्शन द्वारा बुलाया जाता है और पहले से ही मौजूदा ऑर्डरिंग को सुरक्षित रखना होगा। CreateOrderedEnumerable को लागू करने के लिए अपने स्निपेट का उपयोग करना ऑर्डर को ओवरराइड करेगा, जिससे आपका कार्यान्वयन इंटरफ़ेस सेमेन्टिक्स को तोड़ देगा। – Zarat

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