2008-08-19 3 views
68

में एक आईएलआईस्ट को सॉर्ट करना तो मैं आज एक दिलचस्प समस्या में आया। हमारे पास एक डब्ल्यूसीएफ वेब सेवा है जो एक आईएलआईस्ट लौटाती है। वास्तव में एक बड़ा सौदा नहीं है जब तक कि मैं इसे सॉर्ट करना चाहता हूं।सी #

बाहर कर देता है IList इंटरफ़ेस एक तरह से विधि में बनाया नहीं है।

मैं समस्या को हल करने ArrayList.Adapter(list).Sort(new MyComparer()) विधि का उपयोग कर समाप्त हो गया, लेकिन यह सिर्फ मेरे लिए एक बिट "यहूदी बस्ती" लग रहा था।

मैंने आईएलिस्ट से विरासत के साथ एक विस्तार विधि लिखने और अपनी खुद की सॉर्ट() विधि को लागू करने के साथ-साथ एक सूची में कास्टिंग करने के साथ खिलवाड़ किया लेकिन इनमें से कोई भी अत्यधिक सुरुचिपूर्ण लग रहा था।

तो मेरे सवाल है, किसी को भी एक IList

+0

आप पहली जगह में आईएलिस्ट क्यों वापस लौटेंगे? डब्ल्यूसीएफ सेवा से? – DaeMoohn

उत्तर

51

कैसे वस्तुओं के लिए LINQ का उपयोग कर आप के लिए सॉर्ट करने के लिए के बारे में?

कहो तुम एक IList<Car> है, और कार एक Engine संपत्ति थी, मेरा मानना ​​है कि इस प्रकार आप क्रमबद्ध कर सकते हैं:

from c in list 
orderby c.Engine 
select c; 

संपादित करें: आप यहाँ में जवाब पाने के लिए जल्दी होने की जरूरत है। जैसा कि मैंने अन्य उत्तरों के लिए थोड़ा अलग वाक्यविन्यास प्रस्तुत किया है, मैं अपना उत्तर छोड़ दूंगा - हालांकि, प्रस्तुत किए गए अन्य उत्तर समान रूप से मान्य हैं।

+0

यह एक नया समेकित बनाएगा, जो कुछ परिदृश्यों में वांछनीय नहीं हो सकता है। आप मेरे ज्ञान में ArrayList.Adapter विधि का उपयोग करके इंटरफ़ेस के माध्यम से एक IList इन-प्लेस को सॉर्ट नहीं कर सकते हैं। –

9

छँटाई आप की तरह मुझे लगता है कि है कि (यह एक अधिक ठोस प्रकार में बदलने) कुछ करने के लिए जा रहे हैं करने के लिए एक सुरुचिपूर्ण समाधान है।

शायद इसे ऐरेलिस्ट के बजाय टी की सूची में ले जाएं, ताकि आपको तुलनात्मकता को कार्यान्वित करने के तरीके के लिए प्रकार सुरक्षा और अधिक विकल्प मिल सकें।

2

अपने List<T> या कुछ अन्य सामान्य संग्रह में IList कन्वर्ट और फिर आप आसानी से क्वेरी/कर सकते हैं प्रकार यह System.Linq नाम स्थान का उपयोग कर (यह विस्तार तरीकों में से गुच्छा की आपूर्ति करेगा)

+6

'IList ' लागू 'IENumerable 'और इसलिए लिंक ऑपरेशन का उपयोग करने के लिए परिवर्तित करने की आवश्यकता नहीं है। –

56

आप LINQ का उपयोग कर सकते हैं:

using System.Linq; 

IList<Foo> list = new List<Foo>(); 
IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar); 
IList<Foo> sortedList = sortedEnum.ToList(); 
0

यहाँ मजबूत टाइपिंग का उपयोग कर एक उदाहरण है। यकीन नहीं है कि यह जरूरी है कि यह सबसे अच्छा तरीका है।

static void Main(string[] args) 
{ 
    IList list = new List<int>() { 1, 3, 2, 5, 4, 6, 9, 8, 7 }; 
    List<int> stronglyTypedList = new List<int>(Cast<int>(list)); 
    stronglyTypedList.Sort(); 
} 

private static IEnumerable<T> Cast<T>(IEnumerable list) 
{ 
    foreach (T item in list) 
    { 
     yield return item; 
    } 
} 

कास्ट फ़ंक्शन केवल विस्तार विधि का एक पुनर्मूल्यांकन है जो सामान्य स्थिर विधि के रूप में 3.5 के साथ आता है। यह दुर्भाग्य से काफी बदसूरत और verbose है।

0

वीएस 2008 में, जब मैं सेवा संदर्भ पर क्लिक करता हूं और "सेवा संदर्भ कॉन्फ़िगर करें" का चयन करता हूं, तो यह चुनने का विकल्प होता है कि क्लाइंट सेवा से लौटाई गई सूचियों को कैसे क्रमबद्ध करता है।

विशेष रूप से, मैं इस पर एक अच्छी पोस्ट मिले System.Array, System.Collections.ArrayList और System.Collections.Generic.List

0

के बीच चयन और सोचा था कि मैं साझा करते हैं कर सकते हैं। Check it out HERE

मूल रूप से।

आप निम्न वर्ग और IComparer क्लासेस

public class Widget { 
    public string Name = string.Empty; 
    public int Size = 0; 

    public Widget(string name, int size) { 
    this.Name = name; 
    this.Size = size; 
} 
} 

public class WidgetNameSorter : IComparer<Widget> { 
    public int Compare(Widget x, Widget y) { 
     return x.Name.CompareTo(y.Name); 
} 
} 

public class WidgetSizeSorter : IComparer<Widget> { 
    public int Compare(Widget x, Widget y) { 
    return x.Size.CompareTo(y.Size); 
} 
} 

तब यदि आप एक IList है, तो आप इसे इस तरह सॉर्ट कर सकते हैं बना सकते हैं।

List<Widget> widgets = new List<Widget>(); 
widgets.Add(new Widget("Zeta", 6)); 
widgets.Add(new Widget("Beta", 3)); 
widgets.Add(new Widget("Alpha", 9)); 

widgets.Sort(new WidgetNameSorter()); 
widgets.Sort(new WidgetSizeSorter()); 

लेकिन अधिक जानकारी के लिए इस साइट पर देखें ... Check it out HERE

0
using System.Linq; 

var yourList = SomeDAO.GetRandomThings(); 
yourList.ToList().Sort((thing, randomThing) => thing.CompareThisProperty.CompareTo(randomThing.CompareThisProperty)); 

है यह सुंदर! यहूदी बस्ती।

1

इस धागे को मिला जब मैं मूल पोस्ट में वर्णित सटीक समस्या का हल ढूंढ रहा था। हालांकि, कोई भी जवाब मेरी स्थिति पूरी तरह से पूरा नहीं हुआ। ब्रॉडी का जवाब बहुत करीब था। यहां मेरी स्थिति और समाधान है जो मैंने पाया।

मेरे पास एनएचबर्ननेट द्वारा लौटाए गए एक ही प्रकार के दो आईएलिस्ट हैं और दो आईएलिस्ट को एक में उभरा है, इसलिए सॉर्टिंग की आवश्यकता है।

ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList 
:

public class FormatCcdeSorter:IComparer<ReportFormat> 
    { 
     public int Compare(ReportFormat x, ReportFormat y) 
     { 
      return x.FormatCode.CompareTo(y.FormatCode); 
     } 
    } 

मैं तो एक ही प्रकार की एक सरणी के लिए मर्ज किया IList कन्वर्ट:

तरह ब्रोडी मैं वस्तु (ReportFormat) पर एक ICompare लागू किया जो मेरे IList के प्रकार है कहा

तब सरणी क्रमबद्ध करें:

Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer 

के बाद से एक आयामी सरणी मैं लागू करता है nterface System.Collections.Generic.IList<T>, सरणी मूल IList की तरह ही उपयोग किया जा सकता है।

+0

यह करने का यह सही तरीका है। – user29964

0

क्या यह एक वैध समाधान है?

 IList<string> ilist = new List<string>(); 
     ilist.Add("B"); 
     ilist.Add("A"); 
     ilist.Add("C"); 

     Console.WriteLine("IList"); 
     foreach (string val in ilist) 
      Console.WriteLine(val); 
     Console.WriteLine(); 

     List<string> list = (List<string>)ilist; 
     list.Sort(); 
     Console.WriteLine("List"); 
     foreach (string val in list) 
      Console.WriteLine(val); 
     Console.WriteLine(); 

     list = null; 

     Console.WriteLine("IList again"); 
     foreach (string val in ilist) 
      Console.WriteLine(val); 
     Console.WriteLine(); 

परिणाम था: IList बी एक सी

सूची एक बी सी

IList फिर एक बी सी

+0

मान्य अगर यह वास्तव में एक सूची है। कुछ मामलों में, आपके पास अन्य प्रकार हैं जो IList (उदाहरण के लिए, एक सादा सरणी) लागू करते हैं जहां डाउनकास्ट काम नहीं करेगा। बहुत बुरा है कि सॉर्ट() विधि IList के लिए एक विस्तार विधि नहीं है। – Cygon

1

ग्रिड के लिए उपयोगी छँटाई इस विधि की सूची है संपत्ति के नाम पर आधारित है। उदाहरण के रूप में पालन करें।

List<MeuTeste> temp = new List<MeuTeste>(); 

    temp.Add(new MeuTeste(2, "ramster", DateTime.Now)); 
    temp.Add(new MeuTeste(1, "ball", DateTime.Now)); 
    temp.Add(new MeuTeste(8, "gimm", DateTime.Now)); 
    temp.Add(new MeuTeste(3, "dies", DateTime.Now)); 
    temp.Add(new MeuTeste(9, "random", DateTime.Now)); 
    temp.Add(new MeuTeste(5, "call", DateTime.Now)); 
    temp.Add(new MeuTeste(6, "simple", DateTime.Now)); 
    temp.Add(new MeuTeste(7, "silver", DateTime.Now)); 
    temp.Add(new MeuTeste(4, "inn", DateTime.Now)); 

    SortList(ref temp, SortDirection.Ascending, "MyProperty"); 

    private void SortList<T>(
    ref List<T> lista 
    , SortDirection sort 
    , string propertyToOrder) 
    { 
     if (!string.IsNullOrEmpty(propertyToOrder) 
     && lista != null 
     && lista.Count > 0) 
     { 
      Type t = lista[0].GetType(); 

      if (sort == SortDirection.Ascending) 
      { 
       lista = lista.OrderBy(
        a => t.InvokeMember(
         propertyToOrder 
         , System.Reflection.BindingFlags.GetProperty 
         , null 
         , a 
         , null 
        ) 
       ).ToList(); 
      } 
      else 
      { 
       lista = lista.OrderByDescending(
        a => t.InvokeMember(
         propertyToOrder 
         , System.Reflection.BindingFlags.GetProperty 
         , null 
         , a 
         , null 
        ) 
       ).ToList(); 
      } 
     } 
    } 
49

यह सवाल मुझे एक ब्लॉग पोस्ट लिखने के लिए प्रेरित: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

मुझे लगता है कि, आदर्श, .नेट फ्रेमवर्क एक स्थिर सॉर्टिंग विधि है कि एक IList < टी > स्वीकार करता है, को शामिल किया जाएगा, लेकिन सबसे अच्छा अगले चीज अपनी खुद की विस्तार विधि बनाना है। कुछ विधियों को बनाने में बहुत मुश्किल नहीं है जो आपको एक IList < टी > सॉर्ट करने की अनुमति देगी क्योंकि आप एक सूची < टी > सूचीबद्ध करेंगे। बोनस के रूप में आप एक ही तकनीक का उपयोग कर LINQ ऑर्डरबी एक्सटेंशन विधि को अधिभारित कर सकते हैं, ताकि आप List.Sort, IList.Sort, या IEnumerable.OrderBy का उपयोग कर रहे हों, तो आप सटीक उसी वाक्यविन्यास का उपयोग कर सकते हैं।

public static class SortExtensions 
{ 
    // Sorts an IList<T> in place. 
    public static void Sort<T>(this IList<T> list, Comparison<T> comparison) 
    { 
     ArrayList.Adapter((IList)list).Sort(new ComparisonComparer<T>(comparison)); 
    } 

    // Convenience method on IEnumerable<T> to allow passing of a 
    // Comparison<T> delegate to the OrderBy method. 
    public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, Comparison<T> comparison) 
    { 
     return list.OrderBy(t => t, new ComparisonComparer<T>(comparison)); 
    } 
} 

// Wraps a generic Comparison<T> delegate in an IComparer to make it easy 
// to use a lambda expression for methods that take an IComparer or IComparer<T> 
public class ComparisonComparer<T> : IComparer<T>, IComparer 
{ 
    private readonly Comparison<T> _comparison; 

    public ComparisonComparer(Comparison<T> comparison) 
    { 
     _comparison = comparison; 
    } 

    public int Compare(T x, T y) 
    { 
     return _comparison(x, y); 
    } 

    public int Compare(object o1, object o2) 
    { 
     return _comparison((T)o1, (T)o2); 
    } 
} 
इन एक्सटेंशन के साथ

, तरह अपने आप जैसे IList होगा एक सूची:

IList<string> iList = new [] 
{ 
    "Carlton", "Alison", "Bob", "Eric", "David" 
}; 

// Use the custom extensions: 

// Sort in-place, by string length 
iList.Sort((s1, s2) => s1.Length.CompareTo(s2.Length)); 

// Or use OrderBy() 
IEnumerable<string> ordered = iList.OrderBy((s1, s2) => s1.Length.CompareTo(s2.Length)); 

वहाँ पोस्ट में और अधिक जानकारी है: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

+0

सही दृष्टिकोण वास्तव में 'ISortableList ' इंटरफ़ेस (कुछ विशेष तुलनाकर्ता का उपयोग करके सूची के एक हिस्से को सॉर्ट करने के तरीकों के साथ) प्रदान करने के लिए किया गया था, 'सूची ' इसे कार्यान्वित करें, और एक स्थिर विधि है जो किसी भी ' ILI 'यह जांच कर रहा है कि क्या यह' ISortableList 'लागू किया गया है और यदि नहीं, तो इसे एक सरणी में कॉपी करना, उसे क्रमबद्ध करना, 'IList ' को साफ़ करना, और आइटम को दोबारा जोड़ना। – supercat

+3

अद्भुत जवाब! हालांकि, सावधानी बरतने का एक शब्द: यह दृष्टिकोण मानता है कि 'IList सूची' को गैर-सामान्य' IList' इंटरफ़ेस में डाला जा सकता है। यदि आप 'IList ' इंटरफ़ेस को लागू करने के लिए अपनी कक्षा को कोड करते हैं, तो सुनिश्चित करें कि आप गैर-जेनेरिक 'IList' इंटरफ़ेस को भी लागू करते हैं, या कोड क्लास कास्ट अपवाद के साथ विफल हो जाएगा। – sstan

0
try this **USE ORDER BY** : 

    public class Employee 
    { 
     public string Id { get; set; } 
     public string Name { get; set; } 
    } 

private static IList<Employee> GetItems() 
     { 
      List<Employee> lst = new List<Employee>(); 

      lst.Add(new Employee { Id = "1", Name = "Emp1" }); 
      lst.Add(new Employee { Id = "2", Name = "Emp2" }); 
      lst.Add(new Employee { Id = "7", Name = "Emp7" }); 
      lst.Add(new Employee { Id = "4", Name = "Emp4" }); 
      lst.Add(new Employee { Id = "5", Name = "Emp5" }); 
      lst.Add(new Employee { Id = "6", Name = "Emp6" }); 
      lst.Add(new Employee { Id = "3", Name = "Emp3" }); 

      return lst; 
     } 

**var lst = GetItems().AsEnumerable(); 

      var orderedLst = lst.OrderBy(t => t.Id).ToList(); 

      orderedLst.ForEach(emp => Console.WriteLine("Id - {0} Name -{1}", emp.Id, emp.Name));** 
4

@DavidMills द्वारा स्वीकार कर लिया जवाब है काफी अच्छा है, लेकिन मुझे लगता है कि इसे बेहतर किया जा सकता है। एक के लिए, ComparisonComparer<T> कक्षा को परिभाषित करने की आवश्यकता नहीं है जब ढांचे में पहले से ही एक स्थिर विधि Comparer<T>.Create(Comparison<T>) शामिल है। इस विधि का उपयोग फ्लाई पर IComparison बनाने के लिए किया जा सकता है।

इसके अलावा, यह IList<T> से IList पर खतरनाक होने की संभावना है। अधिकांश मामलों में मैंने देखा है, List<T> जो IList लागू करता है IList<T> को लागू करने के लिए दृश्यों के पीछे उपयोग किया जाता है, लेकिन इसकी गारंटी नहीं है और भंगुर कोड का कारण बन सकता है।

आखिरकार, अधिभारित List<T>.Sort() विधि में 4 हस्ताक्षर हैं और उनमें से केवल 2 लागू किए गए हैं।

public static class IListExtensions 
{ 
    public static void Sort<T>(this IList<T> list) 
    { 
     if (list is List<T>) 
     { 
      ((List<T>)list).Sort(); 
     } 
     else 
     { 
      List<T> copy = new List<T>(list); 
      copy.Sort(); 
      Copy(copy, 0, list, 0, list.Count); 
     } 
    } 

    public static void Sort<T>(this IList<T> list, Comparison<T> comparison) 
    { 
     if (list is List<T>) 
     { 
      ((List<T>)list).Sort(comparison); 
     } 
     else 
     { 
      List<T> copy = new List<T>(list); 
      copy.Sort(comparison); 
      Copy(copy, 0, list, 0, list.Count); 
     } 
    } 

    public static void Sort<T>(this IList<T> list, IComparer<T> comparer) 
    { 
     if (list is List<T>) 
     { 
      ((List<T>)list).Sort(comparer); 
     } 
     else 
     { 
      List<T> copy = new List<T>(list); 
      copy.Sort(comparer); 
      Copy(copy, 0, list, 0, list.Count); 
     } 
    } 

    public static void Sort<T>(this IList<T> list, int index, int count, 
     IComparer<T> comparer) 
    { 
     if (list is List<T>) 
     { 
      ((List<T>)list).Sort(index, count, comparer); 
     } 
     else 
     { 
      List<T> range = new List<T>(count); 
      for (int i = 0; i < count; i++) 
      { 
       range.Add(list[index + i]); 
      } 
      range.Sort(comparer); 
      Copy(range, 0, list, index, count); 
     } 
    } 

    private static void Copy(IList<T> sourceList, int sourceIndex, 
     IList<T> destinationList, int destinationIndex, int count) 
    { 
     for (int i = 0; i < count; i++) 
     { 
      destinationList[destinationIndex + i] = sourceList[sourceIndex + i]; 
     } 
    } 
} 
:

  1. List<T>.Sort()
  2. List<T>.Sort(Comparison<T>)
  3. List<T>.Sort(IComparer<T>)
  4. List<T>.Sort(Int32, Int32, IComparer<T>)

नीचे वर्ग IList<T> इंटरफेस के लिए सभी 4 List<T>.Sort() हस्ताक्षर लागू करता है

उपयोग:

class Foo 
{ 
    public int Bar; 

    public Foo(int bar) { this.Bar = bar; } 
} 

void TestSort() 
{ 
    IList<int> ints = new List<int>() { 1, 4, 5, 3, 2 }; 
    IList<Foo> foos = new List<Foo>() 
    { 
     new Foo(1), 
     new Foo(4), 
     new Foo(5), 
     new Foo(3), 
     new Foo(2), 
    }; 

    ints.Sort(); 
    foos.Sort((x, y) => Comparer<int>.Default.Compare(x.Bar, y.Bar)); 
} 

विचार यहाँ अंतर्निहित List<T> की कार्यक्षमता का लाभ उठाने के लिए जब भी संभव छँटाई को संभालने के लिए है। दोबारा, अधिकांश IList<T> कार्यान्वयन जो मैंने देखा है इसका उपयोग करते हैं। उस स्थिति में जब अंतर्निहित संग्रह एक अलग प्रकार है, इनपुट सूची के तत्वों के साथ List<T> का नया उदाहरण बनाने के लिए फ़ॉलबैक, सॉर्टिंग करने के लिए इसका उपयोग करें, फिर परिणामों को वापस इनपुट सूची में कॉपी करें। यह तब भी काम करेगा जब इनपुट सूची IList इंटरफ़ेस को लागू नहीं करती है।