2016-01-28 8 views
7

मुझे OrderBy() जैसी विधि चाहिए जो हमेशा उच्चारण अक्षरों को अनदेखा करने और उन्हें गैर-उच्चारण की तरह देखने के लिए आदेश देता है। मैंने पहले ही OrderBy() को ओवरराइड करने का प्रयास किया है लेकिन ऐसा लगता है कि मैं ऐसा नहीं कर सकता क्योंकि यह एक स्थिर विधि है।ऑर्डरबेटेड अक्षरों से अनदेखा

तो अब मैं OrderBy() के लिए एक कस्टम लैम्ब्डा अभिव्यक्ति बनाना चाहते हैं, इस तरह:

public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(
    this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) 
{ 
    if(source == null) 
     return null; 

    var seenKeys = new HashSet<TKey>(); 

    var culture = new CultureInfo("pt-PT"); 
    return source.OrderBy(element => seenKeys.Add(keySelector(element)), 
          StringComparer.Create(culture, false)); 
} 

हालांकि, मैं इस त्रुटि हो रही है:

Error 2 The type arguments for method 'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TKey>, System.Collections.Generic.IComparer<TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

लगता है यह StringComparer पसंद नहीं है । इसे कैसे हल किया जा सकता है?

नोट:

मैं पहले से ही here से RemoveDiacritics() का उपयोग करने की कोशिश की, लेकिन मैं इस मामले में है कि विधि का उपयोग करने के लिए कैसे पता नहीं है। तो मैंने कुछ ऐसा करने की कोशिश की जैसे this जो भी अच्छा लगता है।

+0

क्या आप Linq2Sql या LinqObjects का उपयोग कर रहे हैं? –

+1

हैशसेट के लिए क्या है? – usr

उत्तर

2

हल! मुझे यह त्रुटि मिल रही थी क्योंकि StringComparerOrderBy() अभिव्यक्ति में सॉर्ट करने के लिए तत्व का उपयोग करने के लिए तत्व को string होना चाहिए।

तो जब मुझे पता है कि तत्व एक स्ट्रिंग है तो मैं एक स्ट्रिंग पर डालता हूं और मैं RemoveDiacritics() विधि का उपयोग उच्चारण अक्षरों को अनदेखा करने और गैर-उच्चारण की तरह देखने के लिए करता हूं।

public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) 
{ 
    if(!source.SafeAny()) 
     return null; 

    return source.OrderBy(element => Utils.RemoveDiacritics(keySelector(element).ToString())); 
} 

की गारंटी करने के लिए RemoveDiacritics() ठीक काम करता है मैं एक HtmlDecode() पंक्ति जोड़ें।

public static string RemoveDiacritics(string text) 
{ 
    if(text != null) 
     text = WebUtility.HtmlDecode(text); 

    string formD = text.Normalize(NormalizationForm.FormD); 
    StringBuilder sb = new StringBuilder(); 

    foreach (char ch in formD) 
    { 
     UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch); 
     if (uc != UnicodeCategory.NonSpacingMark) 
     { 
      sb.Append(ch); 
     } 
    } 

    return sb.ToString().Normalize(NormalizationForm.FormC); 
} 
+1

पर कॉल कर सकते हैं 'आपके' toOrderBy 'को लागू करने की बिल्कुल आवश्यकता नहीं है। यदि आपके पास है 'माईस्ट्रिंग्स' नामक एक स्ट्रिंग गणना आप बस 'mystrings.OrderBy (RemoveDiacritics, StringComparer.Create (संस्कृति, झूठी)) को कॉल कर सकते हैं' –

+0

@ RenéVogt मुझे पता है, लेकिन मैं प्रदर्शन करना चाहता हूं क्योंकि मेरी परियोजना बहुत बड़ी है और मैं नहीं चाहता मेरे प्रोजेक्ट में 'ToOrderBy()' का उपयोग करने के लिए ReneVogt को सभी प्रोजेक्ट – Ninita

+0

@ में संशोधन करने के लिए मुझे केवल Ctrl + F करने की आवश्यकता है और 'ऑर्डर बी' ('' .oOrderBy 'के साथ' 'और' भविष्य में यदि मुझे आवश्यकता है इस तर्क में कुछ बदलना मुझे केवल एक ही स्थान पर बदलने की जरूरत है, न कि पूरे प्रोजेक्ट में। यहां मेरा प्रदर्शन है। अपवाद के लिए मेरे पास 'सुरक्षित'() विधि है जहां मैं जांचता हूं कि शून्य नहीं है और कोई तत्व है। – Ninita

2

OrderBy पहले तर्क के रूप में keySelector लेता है। यह keySelectorFunc<string,T> होना चाहिए। तो आपको एक ऐसी विधि की आवश्यकता है जो एक स्ट्रिंग लेता है और मान देता है जिसके द्वारा आपकी गणना को सॉर्ट किया जाना चाहिए।

दुर्भाग्यवश मुझे यकीन नहीं है कि यह निर्धारित करने के लिए कि कोई चरित्र "उच्चारण पत्र" है या नहीं। RemoveDiacritics मेरे é के लिए काम नहीं करता है।

public bool IsAccentedLetter(char c) 
{ 
    // I'm afraid this does NOT really do the job 
    return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark; 
} 

तो तुम इस तरह अपनी सूची सॉर्ट कर सकते हैं:

string[] myStrings = getStrings(); // whereever your strings come from 
var ordered = myStrings.OrderBy(s => new string(s.Select(c => 
    IsAccentedLetter(c) ? ' ' : c).ToArray()), StringComparer.Create(culture, false)); 

लैम्ब्डा अभिव्यक्ति लेता

तो चलो मान लें कि आपके एक विधि IsAccentedLetter कहा जाता है कि यदि एक चरित्र एक उच्चारण चिह्न पत्र है निर्धारित करता है चलो एक स्ट्रिंग और एक ही स्ट्रिंग देता है, लेकिन एक खाली स्थान के साथ उच्चारण अक्षरों को बदल दिया।
OrderBy अब इन तारों से आपकी गणना को टाइप करता है, और इसलिए उच्चारण अक्षरों को "अनदेखा" करता है।

अद्यतन: आप एक काम कर विधि RemoveDiacritics(string s) कि आप चाहते हैं के रूप में प्रतिस्थापित उच्चारण चिह्न वाले अक्षरों के साथ तार देता है, तो आप बस OrderBy इस तरह कह सकते हैं:

string[] mystrings = getStrings(); 
var ordered = myStrings.OrderBy(RemoveDiacritics, StringComparer.Create(culture, false)); 
+0

कि तर्क मुझे त्रुटि देता है '' TSource 'में' चयन 'की परिभाषा नहीं है और' TSource 'प्रकार के पहले तर्क को स्वीकार करने के लिए कोई भी एक्सटेंशन विधि' चयन 'नहीं मिल सकती है (क्या आप एक निर्देश या एक असेंबली संदर्भ का उपयोग कर रहे हैं ?) '। इसके अलावा आप एक सफेद जगह के साथ उच्चारण पत्र को बदल रहे हैं और मैं चाहता हूं कि उच्चारण किए गए पत्र को एक गैर-उच्चारण पत्र की तरह ट्राउट किया जाए। – Ninita

+0

@ निनिता ओह यह एक गलतफहमी थी: मेरा 'स्रोत' आपकी मूल सूची बनना था। मैं अपने 'toOrderBy' एक्सटेंशन को लागू करने का इरादा नहीं रखता था, यह आवश्यक नहीं है! आपके समाधान में, आपको अपने 'ToOrderBy' की आवश्यकता नहीं है, आप केवल 'mystrings.OrderBy (RemoveDiacritics, StringComparer, बनाएं (संस्कृति, झूठी)' –

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