2013-02-14 45 views
5

मैं उपयोगकर्ता को IANA - Protocol Registry से प्रोटोकॉल चुनना आसान बनाने के लिए एक सेवा बनाने की प्रक्रिया में हूं।एक लिनक/लैम्ब्डा अभिव्यक्ति के साथ परिणाम को कुशलतापूर्वक सीमित करने के लिए कैसे करें?

जैसा कि आप कल्पना कर सकते हैं कि http शब्द के लिए रजिस्ट्री को खोजना बहुत सारी हिट खींचता है। चूंकि amt-soap-http उपयोगकर्ता द्वारा सीधे http की तुलना में बहुत कम बार-बार चुना जा रहा है, मैंने फैसला किया कि http से शुरू होने वाली सभी चीज़ों को खींचना एक अच्छा विचार होगा और फिर शेष परिणामों के साथ इसे संयोजित करें।

var records = this._ianaRegistryService.GetAllLike(term).ToList(); 
var results = records.Where(r => r.Name.StartsWith(term)) 
        .OrderBy(r => r.Name) 
        .Concat(records.Where(r => !r.Name.StartsWith(term)) 
            .OrderBy(r => r.Name)) 
        .Take(MaxResultSize); 

दुर्भाग्य से, मुझे लगता है कि मैं आवश्यकता से अपने परिणाम के माध्यम से अधिक बार पुनरावृत्ति कर रहा हूँ:

नीचे लैम्ब्डा अभिव्यक्ति है कि विचार प्रक्रिया का परिणाम है। समय से पहले अनुकूलन विचारों को लैम्ब्डा अभिव्यक्तियों का एक संयोजन है जो ऊपर की तुलना में अधिक कुशल होगा?

+0

जो लोग 'Orderby' और के बीच अंतर पता नहीं है (@Bobson और upvoter) के लिए,' GroupBy + SelectMany': एक 'है n * लॉग (एन)' ऑपरेशन और अन्य 'n ' – I4V

+0

@ I4V उस ज्ञान का उपयोग करना [उत्तर डी स्टेनली प्रदान किया गया] (http://stackoverflow.com/a/14884435/61654) से अधिक कुशल उत्तर है? – ahsteele

+0

ahsteele, मैंने एक दिया था, लेकिन मैंने इसे 3 डाउनवॉट्स के बाद हटा दिया (क्योंकि मैंने लिखा * मैंने अभी तक इसका परीक्षण नहीं किया है *) – I4V

उत्तर

5

यह एक दो कदम आदेश के रूप में और अधिक कुशल हो सकता है:

var results = records.OrderBy(r => r.Name.StartsWith(term) ? 1 : 2) 
        .ThenBy(r => r.Name) 
        .Take(MaxResultSize); 
+0

@ एल.बी. के साथ बात करना बेहतर है डी डी स्टेनली और मेरे कोड के लिए एक और अधिक कुशल विकल्प है? – ahsteele

+0

@DStanley मान लीजिए 'एन = 2 ** 20 (1 एम)', आपका समाधान '1 एम * 20' होगा, लेकिन दो 0.5 एम आइटम सॉर्ट करना' (0.5 एम * 1 9) * 2' होगा। इसके अतिरिक्त, आपके पास 'ThenBy' है जो' (0.5 एम * 1 9) * 2' – I4V

+0

@ एलबी और मेरे पॉल्ट्री 6,800 अंक के साथ है। :) – ahsteele

3

टिप्पणी का प्रयोग समझाने के लिए मुझे क्या करना कठिन हो रही है कोशिश कर रहा हूँ। तो मैं यह एक और जवाब पोस्ट करूंगा। मान लीजिए कि मैं संख्यात्मक क्रम में पहले या अजीब होने के बाद पहले यादृच्छिक पूर्णांक की एक सूची को सॉर्ट करना चाहता हूं (StartsWith को mod 2 के साथ अनुकरण)।

यहां परीक्षण केस है: action2 अन्य उत्तर के समान है।

यदि आप यह कोड चलाते हैं तो आप देखेंगे कि मेरा सुझाव (action1) दो गुना तेज है।

void Test() 
{ 
    Random rnd = new Random(); 
    List<int> records = new List<int>(); 
    for(int i=0;i<2000000;i++) 
    { 
     records.Add(rnd.Next()); 
    } 

    Action action1 =() => 
    { 
     var res1 = records.GroupBy(r => r % 2) 
        .OrderBy(x => x.Key) 
        .Select(x => x.OrderBy(y => y)) 
        .SelectMany(x => x) 
        .ToList(); 
    }; 

    Action action2 =() => 
    { 
     var res2 = records.OrderBy(x => x % 2).ThenBy(x => x).ToList(); 
    }; 


    //Avoid counting JIT 
    action1(); 
    action2(); 


    var sw = Stopwatch.StartNew(); 
    action1(); 
    long t1 = sw.ElapsedMilliseconds; 

    sw.Restart(); 
    action2(); 
    long t2 = sw.ElapsedMilliseconds; 

    Console.WriteLine(t1 + " " + t2); 
} 
+0

समूहों को सॉर्ट करना अलग-अलग रिकॉर्ड को सॉर्ट करने से कम कुशल होता है जब प्रति समूह केवल एक रिकॉर्ड होता है। – Bobson

+0

@ बॉब्सन बस इसे आज़माएं। ** मैं कहता हूं कि यह 2 गुना तेज है ** – I4V

+0

परिणाम ** जब प्रति समूह केवल एक रिकॉर्ड ** ** '3302 615' है। मैंने आपका कोड लिया, 'i' के साथ 'rnd.Next()' को बदल दिया, और '% 2' कॉल निकाला। यह ओपी के सवाल का बहुत करीब अनुमान है, जहां उनकी सूची में प्रत्येक मूल्य अद्वितीय था, और जिस बिंदु को मैं बनाने की कोशिश कर रहा हूं। यदि आप दोनों से दूसरी ऑर्डर सॉर्टिंग भी करते हैं, तो परिणाम '2656 568' हैं। – Bobson