2009-11-03 12 views
67

क्या LINQ का उपयोग कर सूची में पहली आइटम के रूप में id = 10 के आइटम को स्थानांतरित करने का कोई तरीका है?आइटम को शीर्ष सूची में स्थानांतरित करने के लिए LINQ का उपयोग करें

 
Item A - id =5 
Item B - id = 10 
Item C - id =12 
Item D - id =1

इस मामले मैं कैसे सुंदर ढंग से मेरी List<T> संग्रह के शीर्ष करने के मद सी स्थानांतरित कर सकते हैं में?

इस सबसे अच्छा है मैं अभी है:

var allCountries = repository.GetCountries(); 
var topitem = allCountries.Single(x => x.id == 592); 
var finalList = new List<Country>(); 
finalList.Add(topitem); 
finalList = finalList.Concat(allCountries.Where(x=> x.id != 592)).ToList(); 
+0

आप शीर्ष आइटम के साथ आइटम स्वैप या नीचे पाया आइटम जब तक सभी वस्तुओं धक्का द्वारा आइटम घुमाना चाहते हैं। – AnthonyWJones

+0

बस बाकी को दबाएं – qui

उत्तर

45

LINQ संग्रह की क्वेरी मौजूदा अधिक क्वेरी का अनुमानों बनाने या मौजूदा संग्रह के आधार पर नए प्रश्नों को पैदा करने में मज़बूत है। यह मौजूदा संग्रह इनलाइन को फिर से ऑर्डर करने के लिए एक उपकरण के रूप में नहीं है। उस प्रकार के ऑपरेशन के लिए इस प्रकार का उपयोग करने के लिए सबसे अच्छा है।

मान लिया जाये कि आप

class Item { 
    public int Id { get; set; } 
    .. 
} 

नीचे के रूप में एक समान परिभाषा के साथ एक प्रकार है तो फिर कोशिश निम्नलिखित

List<Item> list = GetTheList(); 
var index = list.FindIndex(x => x.Id == 12); 
var item = list[index]; 
list[index] = list[0]; 
list[0] = item; 
+2

+1 स्वैप परिदृश्य के लिए अच्छी तरह से काम करता है, मुझे यह महसूस करना होगा कि वास्तव में एक घुमाव की आवश्यकता है ' – AnthonyWJones

+0

यह कम या कम है जो मैंने किसी भी तरह से किया है, लेकिन स्पष्टीकरण के लिए धन्यवाद कि क्यों है प्रतीत होता है कि एक बेहतर तरीका नहीं है :) – qui

+5

त्रुटि प्रबंधन के लिए, ध्यान दें कि आपको 'FindIndex' परिणाम मान की जांच करनी चाहिए, यह -1 है यदि आइटम सूची में नहीं मिलता है। – schnaader

31

Enumerables पर Linq generallyworks, तो यह कि अंतर्निहित प्रकार नहीं है करता है एक संग्रह। तो सूची के शीर्ष पर आइटम ले जाने के लिए मैं की तरह कुछ का उपयोग कर अपने समारोह केवल एक IEnumerable देता है, तो

var idx = myList.FindIndex(x => x.id == 592); 
var item = myList[idx]; 
myList.RemoveAt(idx); 
myList.Insert(0, item); 

(यदि आप क्रम बनाए रखने की जरूरत है) सुझाव है, आप के लिए यह कन्वर्ट करने के लिए ToList() विधि का उपयोग कर सकते हैं एक सूची पहले

आप आप बस स्थिति 0 और स्थिति IDX पर मूल्यों की रक्षा स्वैप कर सकते हैं नहीं है, तो

+0

यह केवल मूल्यों को स्वैप करने के बजाय घुमावदार परिदृश्य के लिए एकदम सही है। –

114

क्या जाना जाता शीर्ष आइटम के अलावा, आप से ऑर्डर करने के लिए करना चाहते हैं? आप परवाह नहीं है, तो आप ऐसा कर सकते हैं:

var query = allCountries.OrderBy(x => x.id != 592).ToList(); 

असल में, "गलत" से पहले आता है "सही" ...

वैसे मैं नहीं जानता कि क्या इस एसक्यूएल आदि के लिए LINQ में करता है आपको डेटाबेस में ऑर्डर करने से रोकने की आवश्यकता हो सकती है:

var query = allCountries.AsEnumerable() 
         .OrderBy(x => x.id != 592) 
         .ToList(); 
+1

यह LINQ से SQL के लिए अपेक्षित काम नहीं करता है। मैंने अभी इसका परीक्षण किया। – Yasser

+2

+1 धन्यवाद जॉन। मैं नाम से ऑर्डर करना चाहता था लेकिन आइटम को आईडी = 0 के साथ शीर्ष पर रखना चाहता था इसलिए मैंने यह किया: allCountries.OrderBy (x => x.id == 0? "00000": x.Name) .ToList(); प्रदर्शन एक मुद्दा नहीं है क्योंकि सूची छोटी है। – nima

+2

किसी के बाद कोड की समीक्षा करने के लिए यह स्पष्ट नहीं हो सकता है कि बूलियन मानों को "झूठा, सत्य" आदेश दिया गया है। मैं इस पर अधिक verbose समाधान की सिफारिश करेंगे। – rymdsmurf

9

यहां एक विस्तार विधि है जिसका आप उपयोग करना चाहते हैं। यह तत्व (ओं) को चलाता है जो दिए गए पूर्वानुमान को शीर्ष पर, आदेश को संरक्षित करते हैं।

public static IEnumerable<T> MoveToTop(IEnumerable<T> list, Func<T, bool> func) { 
    return list.Where(func) 
       .Concat(list.Where(item => !func(item))); 
} 

जटिलता के संदर्भ में, मुझे लगता है कि यह संग्रह पर दो गुजरता होगा, यह हे (एन) बनाने, सम्मिलित करें/संस्करण निकालें की तरह है, लेकिन जॉन स्कीट के OrderBy सुझाव की तुलना में बेहतर।

1
public static IEnumerable<T> ServeFirst<T>(this IEnumerable<T> source, 
    Predicate<T> p) 
{ 
    var list = new List<T>(); 

    foreach (var s in source) 
    { 
     if (p(s)) 
      yield return s; 
     else 
      list.Add(s); 
    } 

    foreach (var s in list) 
     yield return s; 
} 
1

यह समस्या हल करने की कोशिश करते समय आपको मिलने वाले दृष्टिकोणों की संख्या दिलचस्प है।

var service = AutogateProcessorService.GetInstance(); 
var allConfigs = service.GetAll(); 
allConfigs = allConfigs.OrderBy(c => c.ThreadDescription).ToList(); 
var systemQueue = allConfigs.First(c => c.AcquirerId == 0); 
allConfigs.Remove(systemQueue); 
allConfigs.Insert(0, systemQueue); 
1

मैं इस एक वर्ष प्रश्न जानता हूँ, लेकिन मैं इसे इस

class Program 
{ 
    static void Main(string[] args) 
    { 
     var numbers = new int[] { 5, 10, 12, 1 }; 

     var ordered = numbers.OrderBy(num => num != 10 ? num : -1); 

     foreach (var num in ordered) 
     { 
      Console.WriteLine("number is {0}", num); 
     } 

     Console.ReadLine(); 
    } 
} 

इस प्रिंट की तरह किया:

संख्या 10
संख्या है 1
नंबर 5
संख्या है है 12

2

आप "द्वारा समूह" में कर सकते हैं बूलियन कुंजी के साथ दो समूहों, और फिर तरह उन्हें

var finalList= allCountries 
       .GroupBy(x => x.id != 592) 
       .OrderBy(g => g.Key) 
       .SelectMany(g => g.OrderBy(x=> x.id)); 
19
var allCountries = repository.GetCountries(); 
allCountries.OrderByDescending(o => o.id == 12).ThenBy(o => o.id) 

इस सूची के शीर्ष पर आईडी = 12 के साथ ऑब्जेक्ट सम्मिलित और बाकी नीचे घुमाने के लिए, क्रम संरक्षण होगा।

+2

आपके फिक्स का एक स्पष्टीकरण चोट नहीं पहुंचाएगा ... – Markus

+0

यह मेरे लिए काम किया – duyn9uyen

+0

मुझे इस विचार प्रक्रिया से प्यार है, लेकिन डी में 1 की आईडी है, इसलिए यह सी, डी, ए, बी के रूप में आदेश नहीं देगा ? – David

0

भी यह जांचने के लिए आइटम बिना किसी अपवाद के पाया गया था, की तरह कुछ:

var allCountries = repository.GetCountries(); 
var lookup = allCountries.ToLookup(x => x.id == 592); 
var finalList = lookup[true].Concat(looup[false]).ToList(); 
if (lookup[true].Count != 1) YouAreInTrouble(); 
0

मैं एक स्थिर विस्तार विधि लिखा था यह करने के लिए। ध्यान दें कि यह आदेश को संरक्षित नहीं करता है, यह आइटम को आसानी से बदल देता है। यदि आपको आदेश को संरक्षित करने की आवश्यकता है तो आपको एक घूर्णन नहीं करना चाहिए, न कि एक साधारण स्वैप।

/// <summary> 
/// Moves the item to the front of the list if it exists, if it does not it returns false 
/// </summary> 
/// <typeparam name="T"></typeparam> 
/// <param name="collection"></param> 
/// <param name="predicate"></param> 
/// <returns></returns> 
public static bool MoveToFrontOfListWhere<T>(this List<T> collection, Func<T, bool> predicate) 
{ 
    if (collection == null || collection.Count <= 0) return false; 

    int index = -1; 
    for (int i = 0; i < collection.Count; i++) 
    { 
     T element = collection.ElementAt(i); 
     if (!predicate(element)) continue; 
     index = i; 
     break; 
    } 

    if (index == -1) return false; 

    T item = collection[index]; 
    collection[index] = collection[0]; 
    collection[0] = item; 
    return true; 
} 
संबंधित मुद्दे