LINQ आदेश अशक्त स्तंभ द्वारा, जहाँ क्रम आरोही है और नल अंतिम होना चाहिए


141

मैं उत्पादों की सूची उनकी कीमत के आधार पर क्रमबद्ध करने की कोशिश कर रहा हूं।

परिणाम सेट में स्तंभ द्वारा निम्न से उच्च कीमत वाले उत्पादों को सूचीबद्ध करने की आवश्यकता होती है LowestPrice। हालाँकि, यह कॉलम अशक्त है।

मैं सूची को अवरोही क्रम में क्रमबद्ध कर सकता हूँ जैसे:

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null

हालाँकि मैं यह पता नहीं लगा सकता कि यह कैसे आरोही क्रम में क्रमबद्ध हो सकता है।

// i'd like: 100, 101, 102, null, null

11
orderby p.LowestPrice ?? Int.MaxValue;एक सरल तरीका है।
पोस्टमैन

3
@PostMan: हाँ, यह सरल है, यह सही परिणाम प्राप्त करता है, लेकिन OrderByDescending, ThenByस्पष्ट है।
जेसन

@ जेसन, हाँ, मैं इसके लिए वाक्यविन्यास नहीं जानता था orderby, और इसे
ढूंढने के

जवाबों:


160

दोनों कॉलम को एक ही क्रम में रखने का प्रयास करें।

orderby p.LowestPrice.HasValue descending, p.LowestPrice

अन्यथा प्रत्येक ऑर्डरबी संग्रह पर एक अलग ऑपरेशन है जो प्रत्येक बार फिर से ऑर्डर करता है।

यह पहले मान वाले लोगों को ऑर्डर करना चाहिए, "फिर" मूल्य का क्रम।


21
सामान्य गलती, लोग लैमडा सिंटैक्स के साथ भी ऐसा ही करते हैं - का उपयोग करते हुए। थर्डबी के बजाय दो बार।
द्वादश

1
इसने शीर्ष पर मानों के साथ फ़ील्ड को ऑर्डर करने के लिए काम किया और नीचे मैंने इसे इस्तेमाल किया orderby p.LowestPrice == null, p.LowestPrice ascending
शैजुत

@DaveShaw ने टिप के लिए धन्यवाद - विशेष रूप से टिप्पणी एक - बहुत साफ - प्यार इसे
डेमेट्रिस लेप्टोस

86

यह वास्तव में LINQ क्वेरी सिंटैक्स को समझने में मदद करता है और इसे LINQ विधि कॉल में कैसे अनुवादित किया जाता है।

परिणाम यह निकला

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;

संकलक द्वारा अनुवाद किया जाएगा

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);

यह सशक्त रूप से वह नहीं है जो आप चाहते हैं। द्वारा इस प्रकार Product.LowestPrice.HasValueमें descendingआदेश और उसके बाद फिर से क्रमबद्ध करता द्वारा पूरे संग्रह Product.LowestPriceमें descendingआदेश।

तुम जो चाहते हो

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);

जिसके द्वारा आप क्वेरी सिंटैक्स का उपयोग करके प्राप्त कर सकते हैं

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;

क्वेरी सिंटैक्स से मेथड कॉल के अनुवाद के विवरण के लिए, भाषा विनिर्देश देखें। गंभीरता से। इसे पढ़ें।


4
+1 या बस ... LINQ क्वेरी सिंटैक्स न लिखें :) अच्छी व्याख्या फिर भी
se

18

स्ट्रिंग मानों के लिए समाधान वास्तव में अजीब है:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString) 

एकमात्र कारण जो काम करता है, क्योंकि पहली अभिव्यक्ति OrderBy(), प्रकार, boolमान: true/ falsefalseपरिणाम पहले trueपरिणाम (nullables) द्वारा जाएं और ThenBy()गैर-शून्य मानों को वर्णानुक्रम से सॉर्ट करें।

इसलिए, मैं इस तरह के रूप में कुछ और पढ़ने योग्य करना पसंद करता हूं:

.OrderBy(f => f.SomeString ?? "z")

यदि SomeStringअशक्त है, तो इसे बदल दिया जाएगा "z"और फिर सब कुछ वर्णानुक्रम में क्रमबद्ध किया जाएगा ।

ध्यान दें: यह एक अंतिम समाधान नहीं है क्योंकि "z"यह z- मानों की तरह पहले जाता है zebra

UPDATE 9/6/2016 - @jornhd टिप्पणी के बारे में, यह वास्तव में एक अच्छा समाधान है, लेकिन यह अभी भी थोड़ा जटिल है, इसलिए मैं इसे विस्तार वर्ग में लपेटने की सलाह दूंगा, जैसे कि:

public static class MyExtensions
{
    public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector)
    {
        return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector);
    }
}

और सरल का उपयोग करें जैसे:

var sortedList = list.NullableOrderBy(f => f.SomeString);

2
मुझे लगता है कि यह अधिक पठनीय है, बुरा निरंतर बिना: .OrderBy (च => f.SomeString = अशक्त 0: 1!?) .ThenBy (च => f.SomeString)
jornhd

14

मेरे पास इस स्थिति में एक और विकल्प है। मेरी सूची objList है, और मुझे आदेश देना है लेकिन नल अंत में होना चाहिए। मेरा निर्णय:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));

यह उन परिदृश्यों में काम कर सकता है, जहां कोई शून्य के स्थान पर 0 जैसे अन्य मूल्यों के साथ परिणाम चाहता है।
नरेश रावलानी

हाँ। बस null को 0.
Gurgen Hovsepyan

यह एकमात्र उत्तर है जो मेरे लिए काम करता है, बाकी ने सूची की शुरुआत में नल को रखा।
बीएमआईएल

9

मैं इस के लिए एक LINQ समाधान खोजने की कोशिश कर रहा था, लेकिन यहाँ जवाब से यह काम नहीं कर सका।

मेरा अंतिम उत्तर था:

.OrderByDescending(p => p.LowestPrice.HasValue).ThenBy(p => p.LowestPrice)

7

मेरा निर्णय:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)

7

यही कारण है कि मैं साथ आया हूं क्योंकि मैं विस्तार विधियों का उपयोग कर रहा हूं और साथ ही मेरा आइटम एक स्ट्रिंग है, इस प्रकार नहीं .HasValue:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)

यह LINQ 2 ऑब्जेक्ट्स के साथ मेमोरी में काम करता है। मैंने ईएफ या किसी डीबी ओआरएम के साथ इसका परीक्षण नहीं किया।


0

नीचे विस्तार विधि के लिए नल की जाँच करें यदि आप एक keySelector के बच्चे की संपत्ति पर सॉर्ट करना चाहते हैं।

public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, object> parentKeySelector, Func<T, object> childKeySelector)
{
    return list.OrderBy(v => parentKeySelector(v) != null ? 0 : 1).ThenBy(childKeySelector);
}

और सरल का उपयोग करें जैसे:

var sortedList = list.NullableOrderBy(x => x.someObject, y => y.someObject?.someProperty);

0

यहाँ एक और तरीका है:

//Acsending
case "SUP_APPROVED_IND": qry =
                            qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
                                    ThenBy(r => r.SUP_APPROVED_IND);

                            break;
//….
//Descending
case "SUP_APPROVED_IND": qry =
                            qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
                                    ThenByDescending(r => r.SUP_APPROVED_IND); 

                            break;

SUP_APPROVED_IND is char(1) in Oracle db.

ध्यान दें कि Oracle डीबी के r.SUP_APPROVED_IND.Trim() == nullरूप trim(SUP_APPROVED_IND) is nullमें व्यवहार किया जाता है।

विवरण के लिए इसे देखें: मैं इकाई ढांचे में शून्य मानों के लिए क्वेरी कैसे कर सकता हूं?


0

एक अन्य विकल्प (हमारे परिदृश्य के लिए उपयोगी था):

हमारे पास एक उपयोगकर्ता तालिका है, भंडारण ADName, LastName, FirstName

  • उपयोगकर्ताओं को वर्णानुक्रम होना चाहिए
  • उनके ADName के आधार पर पहले-पहले / LastName के साथ-साथ उपयोगकर्ता-सूची के अंत में खाते
  • ID "0" ("नहीं चयन") के साथ डमी उपयोगकर्ता हमेशा सबसे ऊपर होना चाहिए।

हमने टेबल स्कीमा को बदल दिया और "सॉर्टइंडेक्स" कॉलम जोड़ा, जो कुछ छंटाई समूहों को परिभाषित करता है। (हमने 5 का अंतर छोड़ा, इसलिए हम बाद में समूह सम्मिलित कर सकते हैं)

ID | ADName |      First Name | LastName | SortIndex
0    No Selection  null         null     | 0
1    AD\jon        Jon          Doe      | 5
3    AD\Support    null         null     | 10     
4    AD\Accounting null         null     | 10
5    AD\ama        Amanda       Whatever | 5

अब, क्वेरी-वार यह होगा:

SELECT * FROM User order by SortIndex, LastName, FirstName, AdName;

विधि अभिव्यक्तियों में:

db.User.OrderBy(u => u.SortIndex).ThenBy(u => u.LastName).ThenBy(u => u.FirstName).ThenBy(u => u.AdName).ToList();

जो अपेक्षित परिणाम देता है:

ID | ADName |      First Name | LastName | SortIndex
0    No Selection  null         null     | 0
5    AD\ama        Amanda       Whatever | 5
1    AD\jon        Jon          Doe      | 5
4    AD\Accounting null         null     | 10
3    AD\Support    null         null     | 10     
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.