2013-08-04 3 views
16
List<int> _lstNeedToOrder = new List<int>(); 
_lstNeedToOrder.AddRange(new int[] { 1, 5, 6, 8 }); 

//I need to sort this based on the below list. 

List<int> _lstOrdered = new List<int>();//to order by this list 
_lstOrdered.AddRange(new int[] { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 }); 

order will be -->_lstNeedToOrder = 5,1,8,6 

मैं इसे कैसे कर सकता हूं?बड़ी सूची के आधार पर सूची को सॉर्ट करने के लिए LINQ विधि

उत्तर

19

खैर सरल - लेकिन अक्षम - तरीका होगा:

var result = _lstNeedToOrder.OrderBy(x => _lstOrdered.IndexOf(x)); 

एक वैकल्पिक एक मूल्य के वांछित सूचकांक प्राप्त करने की एक दूर तरह से बाहर काम करने के लिए होगा। यदि आपके मान हमेशा सीमा में होंगे [1 ... n] आप केवल "आदेशित" सूची को "मूल्य से सूचकांक की सूची" में परिवर्तित कर सकते हैं। इसके बाद से आप इस्तेमाल कर सकते हैं:

var result = _lstNeedToOrder.OrderBy(x => indexes[x]); 

(जहां indexes 0 के लिए शुरू में एक अतिरिक्त मूल्य के लिए होता है, सिर्फ बातें सरल बनाने के लिए)।

वैकल्पिक रूप से, आप मूल्य से सूचकांक तक Dictionary<int, int> बना सकते हैं। यह अधिक सामान्य होगा, जिसमें यह बहुत मेमोरी लेने के बिना मूल्यों की एक विस्तृत श्रृंखला को संभालेगा। लेकिन एक शब्दकोश लुकअप एक सरणी या सूची लुकअप से स्पष्ट रूप से कम कुशल है।

बस एक ओर टिप्पणी जो एक टिप्पणी के रूप में अच्छी तरह से स्वरूपित नहीं होगा, क्योंकि

, अपने प्रारंभ एक संग्रह प्रारंभकर्ता का उपयोग कर सरल किया जा सकता:

var listToOrder = new List<int> { 1, 5, 6, 8 }; 
var orderedList = new List<int> { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 }; 
+0

अरे जॉन, क्षमा करें अगर यह एक बेवकूफ सवाल है, लेकिन पहला अक्षम क्यों है? –

+1

@ डिमिटार डिमिट्रोव: प्रत्येक प्रविष्टि की वांछित अनुक्रमणिका खोजने के लिए यह 'इंडेक्सऑफ' का उपयोग करता है। यह अनावश्यक रूप से '_lstOrdered' के आकार पर एक ओ (एन) ऑपरेशन है। –

+0

@DimitarDimitrov शायद क्योंकि 'इंडेक्सऑफ' का उपयोग? –

13
List<int> results = _lstOrdered.Where(item => _lstNeedToOrder.Contains(item)).ToList(); 
+0

दिलचस्प विचार। यह डुप्लिकेट को संभाल नहीं पाएगा, लेकिन हम नहीं जानते कि यह निश्चित रूप से आवश्यक है या नहीं। –

+0

एचएम, मैंने उस मामले के बारे में सोचा नहीं था। :) मुझे लगता है कि यह ओपी तक है चाहे वह आवश्यकताओं में है या नहीं। –

+0

@ वॉननहिल्ट्स, मेरे मामले में कोई डुप्लिकेट नहीं होगा, धन्यवाद! –

1

एक मध्यवर्ती शब्दकोश में सहेजा जा रहा है क्रम ...

यथा-स्थान
// dict key will be the values of _lstOrdered, value will be the index of the 
// key in _lstOrdered 
// I'm using a seldom used .Select overload that returns the current value 
// plus its index (ix) 
var dict = _lstOrdered.Select((p, ix) => new { Value = p, Ix = ix }) 
         .ToDictionary(p => p.Value, p => p.Ix); 

// note that this will explode if _lstNeedToOrder contains values outside 
// _lstOrdered. 
_lstNeedToOrder.Sort((p, q) => dict[p] - dict[q]); 

.Sort विधि प्रकार तो _lstNeedToOrder आदेश दिया की जाएगी।

4

आप इस तरह एक कस्टम comparer निर्माण कर सकते हैं:

public class SequenceComparer<T> : IComparer<T> { 
    private readonly Dictionary<T, int> indexes; 

    public SequenceComparer(IEnumerable<T> sequence) { 
     this.indexes = 
      sequence 
       .Select((item, index) => new { Item = item, Index = index }) 
       .ToDictionary(x => x.Item, x => x.Index); 
    } 

    public int Compare(T x, T y) { 
     return indexes[x].CompareTo(indexes[y]); 
    } 
} 

अब आप कह सकते हैं

var result = _lstNeedToOrder.OrderBy(x => x, new SequenceComparer(_lstOrdered)); 
+0

कक्षा 'अनुक्रम कॉम्पैयर ' का उपयोग कैसे करें, मुझे नहीं लगता कि इसका उपयोग 'ऑर्डरब्य' क्वेरी में कैसे किया जाता है। –

+1

@ किंग किंग: धन्यवाद। मैं इसे 'ऑर्डरबी' पर कॉल में बनाने से चूक गया। यह अभी है एक बार फिर धन्यवाद। – jason

4

यह काफी अच्छी तरह से काम करता है:

var lookup = _lstOrdered 
    .Select((x, n) => new { x, n }) 
    .ToLookup(x => x.x, x => x.n); 

var query = 
    from x in _lstNeedToOrder 
    let rank = lookup[x] 
     .DefaultIfEmpty(int.MaxValue) 
     .First() 
    orderby rank 
    select x; 
2

एक अन्य विकल्प Intersect उपयोग करने के लिए है, जो क्रम में तत्वों को वापस करने की गारंटी देता है जिसमें वे पहले अनुक्रम में दिखाई देते हैं।

तो, इस उदाहरण में

var result = _lstOrdered.Intersect(_lstNeedToOrder); 

पैदावार { 5, 1, 8, 6} के रूप में की आवश्यकता है।

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