2010-07-02 10 views
15

मुझे तारों या संख्याओं की स्मृति सूचियों को आरोही या अवरोही क्रम में क्रमबद्ध करने की आवश्यकता है। हालांकि, सूची में शून्य मान हो सकते हैं और सभी शून्य मान संख्याओं या तारों के बाद प्रकट होना चाहिए।आप LINQ में कस्टम सॉर्टिंग को अंत में हमेशा शून्य के साथ कैसे कर सकते हैं?

है कि इनपुट डेटा हो सकता है:

1, 100, null, 5, 32.3

आरोही परिणाम होगा

1, 5, 32.3, 100, null

उतरते सूची

100, 32.3, 5, 1, null

यह कैसे बनाने के लिए पर कोई भी विचार किया जाएगा काम?

उत्तर

6

आप अपना खुद का तुलनाकर्ता लिख ​​सकते हैं जो गैर-नल के लिए मौजूदा व्यक्ति को प्रतिनिधि करता है, लेकिन अंत में हमेशा नल की तरह चलता है। कुछ इस तरह:

public class NullsLastComparer<T> : IComparer<T> 
{ 
    private readonly IComparer<T> proxy; 

    public NullsLastComparer(IComparer<T> proxy) 
    { 
     this.proxy = proxy; 
    } 

    public override int Compare(T first, T second) 
    { 
     if (first == null && second == null) 
     { 
      return 0; 
     } 
     if (first == null) 
     { 
      return 1; 
     } 
     if (second == null) 
     { 
      return -1; 
     } 
     return proxy.Compare(first, second); 
    } 
} 

संपादित करें: इस दृष्टिकोण के साथ कुछ मुद्दों:

सबसे पहले, यह गुमनाम प्रकार के साथ अच्छी तरह से खेलने नहीं करता है; आपको उस काम को अच्छी तरह से बनाने के लिए एक अलग एक्सटेंशन विधि की आवश्यकता हो सकती है। या केन के उत्तर का उपयोग करें :)

अधिक महत्वपूर्ण बात यह है कि यह IComparer<T> अनुबंध का उल्लंघन करता है, जो निर्दिष्ट करता है कि नल पहले होना चाहिए। अब व्यक्तिगत रूप से, मुझे लगता है कि यह IComparer<T> विनिर्देशन में एक गलती है - इसे शायद परिभाषित करना चाहिए कि तुलनात्मक को नल को संभालना चाहिए, लेकिन निर्दिष्ट नहीं करना चाहिए कि वे पहले या आखिरी बार आते हैं ... यह इस तरह की आवश्यकताओं को बनाता है (जो पूरी तरह से उचित हैं) जितना संभव हो उतना स्वच्छ रूप से पूरा करना असंभव है, और इसमें रिवर्सिंग तुलनाकर्ता जैसी चीजों के लिए सभी प्रकार की अजीब विधियां हैं। आप इस तरह की चीज को पूरी तरह से ऑर्डर करने की अपेक्षा करेंगे, लेकिन spec के अनुसार इसे अभी भी शुरुआत में नल बनाए रखना चाहिए :(

मुझे नहीं लगता कि मैंने किसी भी .NET सॉर्टिंग कार्यान्वयन को देखा है जो वास्तव में भरोसा करता है इस है, लेकिन यह निश्चित रूप से के बारे में पता किया जा रहा लायक है

+0

क्या यह .NET सॉर्टिंग कार्यान्वयन के साथ अनुबंध का उल्लंघन नहीं है? मैंने सोचा कि मैंने कहीं पढ़ा है कि सॉर्टिंग विधियां नल के पहले आ सकती हैं ... या ...? –

+0

@Lasse: यह 'IComparer ' इंटरफ़ेस का उल्लंघन है, हां - मैं इसका उल्लेख करने के लिए अपनी पोस्ट संपादित करूंगा। –

+0

हाँ, लेकिन इस बारे में पढ़ने के दौरान मुझे क्या याद है, ऐसा लगता है कि सॉर्टिंग विधियों को इस अनुबंध के कारण शॉर्टकट ले सकते हैं, और इस प्रकार वास्तव में कुछ मामलों के लिए तुलना विधि को कॉल नहीं करते हैं, क्योंकि यह पहले से ही "पता था" परिणाम क्या था होने जा रहा है। दूसरे शब्दों में, क्या यह कुछ मामलों में फंकी परिणाम नहीं देगा? –

38

मैं मेरे सामने एक संकलक की जाँच करने की जरूरत नहीं है, लेकिन मैं कुछ सोच रहा हूँ:।

x.OrderBy(i => i == null).ThenBy(i => i) 
+3

नाइस ... यह वास्तव में मीठा दृष्टिकोण है। अगर मैं कर सकता था तो मैं इसे एक से अधिक बार वोट दूंगा ... –

+0

बहुत अच्छा। यह दृष्टिकोण लिंक-टू-एंटिटीज के लिए भी काम करता है और यह सही ढंग से एसक्यूएल में अनुवाद करता है। –

0

के रूप में जॉन ने कहा, आप की जरूरत है IComparer को कार्यान्वित करने के लिए अपने कस्टम तुलनाकर्ता को परिभाषित करें। यहां बताया गया है कि कस्टम तुलनात्मक में आपकी Compare विधि कैसा रह सकती है अंत में null

public int Compare(Object x, Object y) 
    { 
     int retVal = 0; 

     IComparable valX = x as IComparable; 
     IComparable valY = y as IComparable; 

     if (valX == null && valY == null) 
     { 
      return 0; 
     } 

     if (valX == null) 
     { 
      return 1; 
     } 
     else if (valY == null) 
     { 
      return -1; 
     } 

     return valX.CompareTo(valY); 
    } 
संबंधित मुद्दे

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