Jadi saya menemukan masalah yang menarik hari ini. Kami memiliki layanan web WCF yang mengembalikan IList. Bukan masalah besar sampai saya ingin mengatasinya.
Ternyata antarmuka IList tidak memiliki metode pengurutan bawaan.
Saya akhirnya menggunakan ArrayList.Adapter(list).Sort(new MyComparer())
metode ini untuk memecahkan masalah tetapi itu hanya tampak sedikit "ghetto" bagi saya.
Saya bermain-main dengan menulis metode ekstensi, juga dengan mewarisi dari IList dan menerapkan metode Sort () saya sendiri serta mentransmisikan ke Daftar tetapi tidak ada yang tampak terlalu elegan.
Jadi pertanyaan saya adalah, apakah ada yang punya solusi elegan untuk menyortir IList
Jawaban:
Bagaimana jika menggunakan LINQ To Objects untuk mengurutkan untuk Anda?
Katakanlah Anda punya
IList<Car>
, dan mobil itu punyaEngine
properti, saya yakin Anda bisa mengurutkan sebagai berikut:from c in list orderby c.Engine select c;
Edit: Anda harus cepat mendapatkan jawaban di sini. Saat saya menyajikan sintaks yang sedikit berbeda dengan jawaban lain, saya akan meninggalkan jawaban saya - namun, jawaban lain yang disajikan sama-sama valid.
sumber
Anda dapat menggunakan LINQ:
using System.Linq; IList<Foo> list = new List<Foo>(); IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar); IList<Foo> sortedList = sortedEnum.ToList();
sumber
Pertanyaan ini menginspirasi saya untuk menulis entri blog: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
Saya pikir, idealnya, .NET Framework akan menyertakan metode penyortiran statis yang menerima IList <T>, tetapi hal terbaik berikutnya adalah membuat metode ekstensi Anda sendiri. Tidak terlalu sulit untuk membuat beberapa metode yang akan memungkinkan Anda mengurutkan IList <T> seperti yang Anda lakukan pada List <T>. Sebagai bonus, Anda dapat membebani metode ekstensi LINQ OrderBy menggunakan teknik yang sama, sehingga baik Anda menggunakan List.Sort, IList.Sort, atau IEnumerable.OrderBy, Anda dapat menggunakan sintaks yang sama persis.
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)); } // Sorts in IList<T> in place, when T is IComparable<T> public static void Sort<T>(this IList<T> list) where T: IComparable<T> { Comparison<T> comparison = (l, r) => l.CompareTo(r); Sort(list, 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); } }
Dengan ekstensi ini, sortir IList Anda seperti yang Anda lakukan pada Daftar:
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));
Ada info lebih lanjut di pos: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
sumber
ISortableList<T>
antarmuka (dengan metode untuk mengurutkan sebagian dari daftar menggunakan beberapa pembanding tertentu), telahList<T>
menerapkannya, dan memiliki metode statis yang dapat mengurutkan apa punIList<T>
dengan memeriksa apakah diterapkanISortableList<T>
dan, jika tidak, menyalinnya ke array, menyortirnya, membersihkanIList<T>
, dan menambahkan kembali item.IList<T> list
dapat dilemparkan keIList
antarmuka non-generik . Jika Anda membuat kode kelas Anda sendiri dengan mengimplementasikanIList<T>
antarmuka, pastikan Anda juga menerapkanIList
antarmuka non-generik , atau kode akan gagal dengan pengecualian cast kelas.ISortableList<T>
ditawarkan yang belum adaIList<T>
? Atau, jika ditanya secara berbeda, mengapa tidakIList<T>
dapat disortir di tempat tanpa menambahkan kembali item dengan metode statis yang Anda bayangkan?IList<T>
antarmuka untuk mengakses setiap elemen. Perbedaan kecepatannya cukup besar sehingga dalam banyak kasus mungkin lebih cepat untuk menyalin daftar ke array, mengurutkan array, dan menyalin daftar kembali, daripada mencoba memiliki proses rutin pengurutan daftar di tempat.ComparisonComparer
kelas tidak diperlukan. Anda dapat menggunakan metode statis standarComparer<T>.Create(comparison)
sebagai gantinya.Saya pikir Anda harus melakukan sesuatu seperti itu (mengubahnya menjadi tipe yang lebih konkret).
Mungkin membawanya ke dalam Daftar T daripada ArrayList, sehingga Anda mendapatkan keamanan tipe dan lebih banyak opsi untuk bagaimana Anda mengimplementasikan pembanding.
sumber
Jawaban yang diterima oleh @DavidMills cukup bagus, tapi menurut saya bisa diperbaiki. Pertama, tidak perlu mendefinisikan
ComparisonComparer<T>
kelas ketika framework sudah menyertakan metode statisComparer<T>.Create(Comparison<T>)
. Metode ini dapat digunakan untuk membuatIComparison
on the fly.Selain itu, gips
IList<T>
untukIList
yang memiliki potensi untuk menjadi berbahaya. Dalam kebanyakan kasus yang saya lihat,List<T>
implementasiIList
yang digunakan di belakang layar untuk diterapkanIList<T>
, tetapi ini tidak dijamin dan dapat menyebabkan kode rapuh.Terakhir,
List<T>.Sort()
metode overload memiliki 4 tanda tangan dan hanya 2 yang diimplementasikan.List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
Kelas di bawah ini mengimplementasikan semua 4
List<T>.Sort()
tanda tangan untukIList<T>
antarmuka:using System; using System.Collections.Generic; 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<T>(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]; } } }
Pemakaian:
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)); }
Idenya di sini adalah untuk memanfaatkan fungsionalitas yang mendasari
List<T>
untuk menangani penyortiran bila memungkinkan. Sekali lagi, sebagian besarIList<T>
implementasi yang saya lihat menggunakan ini. Jika koleksi yang mendasari adalah jenis yang berbeda, mundur untuk membuat instance baruList<T>
dengan elemen dari daftar masukan, gunakan untuk melakukan penyortiran, lalu salin hasilnya kembali ke daftar masukan. Ini akan bekerja bahkan jika daftar masukan tidak mengimplementasikanIList
antarmuka.sumber
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));**
sumber
Menemukan utas ini ketika saya mencari solusi untuk masalah sebenarnya yang dijelaskan dalam posting asli. Namun, tidak ada jawaban yang sesuai dengan situasi saya sepenuhnya. Jawaban Brody cukup dekat. Inilah situasi saya dan solusi yang saya temukan untuk itu.
Saya memiliki dua IList dengan tipe yang sama yang dikembalikan oleh NHibernate dan telah memunculkan dua IList menjadi satu, oleh karena itu perlu penyortiran.
Seperti yang dikatakan Brody, saya menerapkan ICompare pada objek (ReportFormat) yang merupakan jenis IList saya:
public class FormatCcdeSorter:IComparer<ReportFormat> { public int Compare(ReportFormat x, ReportFormat y) { return x.FormatCode.CompareTo(y.FormatCode); } }
Saya kemudian mengonversi IList yang digabungkan menjadi array dengan tipe yang sama:
ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList
Kemudian urutkan array:
Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer
Karena array satu dimensi mengimplementasikan antarmuka
System.Collections.Generic.IList<T>
, array tersebut dapat digunakan seperti IList asli.sumber
Berguna untuk pengurutan grid, metode ini mengurutkan daftar berdasarkan nama properti. Seperti contohnya.
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(); } } }
sumber
Berikut contoh penggunaan pengetikan yang lebih kuat. Tidak yakin apakah itu cara terbaik.
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; } }
Fungsi Cast hanyalah implementasi ulang dari metode ekstensi yang dilengkapi dengan 3.5 yang ditulis sebagai metode statis normal. Sayangnya, ini cukup jelek dan bertele-tele.
sumber
Di VS2008, ketika saya mengklik referensi layanan dan memilih "Konfigurasi Referensi Layanan", ada opsi untuk memilih bagaimana klien membatalkan serialisasi daftar yang dikembalikan dari layanan.
Khususnya, saya dapat memilih antara System.Array, System.Collections.ArrayList dan System.Collections.Generic.List
sumber
using System.Linq; var yourList = SomeDAO.GetRandomThings(); yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) );
Cantik sekali! Ghetto.
sumber
Menemukan postingan yang bagus tentang ini dan saya pikir saya akan membagikannya. Lihat disini
Pada dasarnya.
Anda dapat membuat kelas berikut dan Kelas 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); } }
Kemudian Jika Anda memiliki IList, Anda dapat mengurutkannya seperti ini.
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());
Tapi lihat situs ini untuk informasi lebih lanjut ... Lihat DI SINI
sumber
Apakah ini solusi yang valid?
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();
Hasilnya adalah: IList B A C
Daftar A B C
Nyalakan lagi A B C
sumber
Ini terlihat JAUH LEBIH SEDERHANA jika Anda bertanya kepada saya. Ini bekerja dengan SEMPURNA untuk saya.
Anda bisa menggunakan Cast () untuk mengubahnya menjadi IList kemudian menggunakan OrderBy ():
var ordered = theIList.Cast<T>().OrderBy(e => e);
WHERE T adalah tipe mis. Model.Employee atau Plugin.ContactService.Shared.Contact
Kemudian Anda dapat menggunakan for loop dan SELESAI.
ObservableCollection<Plugin.ContactService.Shared.Contact> ContactItems= new ObservableCollection<Contact>(); foreach (var item in ordered) { ContactItems.Add(item); }
sumber
Ubah Anda
IList
menjadiList<T>
atau beberapa koleksi umum lainnya dan kemudian Anda dapat dengan mudah menanyakan / mengurutkan menggunakanSystem.Linq
namespace (ini akan menyediakan banyak metode ekstensi)sumber
IList<T>
mengimplementasikanIEnumerable<T>
dan oleh karena itu tidak perlu dikonversi untuk menggunakan operasi Linq.