2013-03-07 6 views
61

मैं इस तरह कुछ पहचान का एक सूची है:क्रमबद्ध एक और सूची आईडी से एक सूची

List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 }; 

Morover, मैं <T> आइटम है, जो ऊपर वर्णित आईडी का प्रतिनिधित्व कर रहे की एक और सूची है।

List<T> docs = GetDocsFromDb(...) 

मैं, दोनों संग्रहों में एक ही आदेश रखने की जरूरत है ताकि List<T> में आइटम पहले एक (इंजन स्कोरिंग कारणों खोज करने के लिए कारण) की तुलना में एक ही स्थिति में होना चाहिए। और यह प्रक्रिया GetDocsFromDb() फ़ंक्शन में नहीं की जा सकती है।

यदि आवश्यक हो, तो दूसरी सूची को उदाहरण के लिए किसी अन्य संरचना (Dictionary<long, T>) में बदलना संभव है, लेकिन मैं इसे बदलना नहीं चाहूंगा।

क्या LINQ के साथ "कुछ आईडी के आधार पर ordenation" करने का कोई आसान और कारगर तरीका है?

+0

क्या आपको आश्वासन दिया जाता है कि प्रत्येक 'docId' वास्तव में 'दस्तावेज़' में होता है, कौन सी संपत्ति' आईडी' रखेगी या एक चयनकर्ता 'Func ' आवश्यक होगा? – Jodrell

+0

क्या पहली सूची "मास्टर सूची" का प्रतिनिधित्व करती है? एक और शब्द, क्या दूसरी सूची एक सूची है जो पहली सूची के एक हिस्से (या पूरी तरह) का प्रतिनिधित्व करती है? – code4life

उत्तर

170
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList(); 
+0

@ कैफ यही कारण है कि मैं भी ऊपर उठ गया, दस्तावेज़ आईडी संपत्ति को जानने पर भरोसा करता है जिसे 'आईडी' कहा जाता है। यह सवाल में निर्दिष्ट नहीं है। – Jodrell

+0

@ बोर्ज़ालोपेज़, एक त्वरित नोट। आप अपने प्रश्न में दक्षता का उल्लेख करते हैं। 'इंडेक्सऑफ' आपके उदाहरण और अच्छे और सरल के लिए पूरी तरह से स्वीकार्य है। यदि आपके पास बहुत अधिक डेटा था तो मेरा उत्तर बेहतर अनुकूल हो सकता है। http://stackoverflow.com/questions/3663014/why-is-this-list-indexof-code-so-much-faster-than-the-listi-and-manual-compa – Jodrell

+0

मैंने इस विधि को बेंचमार्क किया है और शब्दकोश के साथ एक (नीचे देखें) और यह लगभग दोगुना तेज़ है। –

-1

एक सरल दृष्टिकोण आदेश अनुक्रम के साथ ज़िप करने है:

List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create) 
       .OrderBy(x => x.Item2).Select(x => x.Item1).ToList(); 
+0

एक ज़िप के बाद आदेश क्यों? – Jodrell

+0

क्योंकि 'ज़िप' संबंधित सूची में उसी स्थिति में दस्तावेज़ के साथ प्रत्येक अनुक्रमणिका (एक टुपल में) को जोड़ती है।फिर ऑर्डरबी इंडेक्स भाग द्वारा टुपल्स को टाइप करता है और फिर चुनिंदा अब ऑर्डर किए गए सूची से हमारे दस्तावेज़ों को खो देता है। –

+0

लेकिन, GetDocsFromDb का परिणाम अनियंत्रित है, इसलिए आप टुपल्स बनायेंगे जहां 'Item1'' Item2' से संबंधित नहीं है। – Jodrell

5

जब से तुम T निर्दिष्ट नहीं करते,

IEnumerable<T> OrderBySequence<T, TId>(
     this IEnumerable<T> source, 
     IEnumerable<TId> order, 
     Func<T, TId> idSelector) 
{ 
    var lookup = source.ToDictionary(idSelector, t => t); 
    foreach (var id in order) 
    { 
     yield return lookup[id]; 
    } 
} 

आप क्या चाहते हैं के लिए एक सामान्य विस्तार है।

आप इस शायद की तरह एक्सटेंशन का उपयोग कर सकता है,

var orderDocs = docs.OrderBySequence(docIds, doc => doc.Id); 

एक सुरक्षित संस्करण

IEnumerable<T> OrderBySequence<T, TId>(
     this IEnumerable<T> source, 
     IEnumerable<TId> order, 
     Func<T, TId> idSelector) 
{ 
    var lookup = source.ToLookup(idSelector, t => t); 
    foreach (var id in order) 
    { 
     foreach (var t in lookup[id]) 
     { 
      yield return t; 
     } 
    } 
} 

हो सकता है अगर sourceorder साथ बिल्कुल ज़िप नहीं है काम करेंगे।

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