Sorting an IList in C#
所以我今天遇到了一个有趣的问题。我们有一个返回IList的WCF Web服务。在我想整理之前没什么大不了的。
结果发现ilist接口没有内置排序方法。
我最终用
我尝试编写一个扩展方法,也尝试从IList继承并实现我自己的sort()方法,并将其强制转换为一个列表,但这些方法看起来都不太优雅。
所以我的问题是,是否有人有一个优雅的解决方案来排序一个IList
您可以使用LINQ:
1 2 3 4 5 | using System.Linq; IList<Foo> list = new List<Foo>(); IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar); IList<Foo> sortedList = sortedEnum.ToList(); |
这个问题启发我写了一篇博文:http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
我认为,理想情况下,.NET框架将包括一个接受IList的静态排序方法,但接下来最好的事情是创建自己的扩展方法。创建两个方法可以像创建列表一样对ilist进行排序,这并不难。另外,您可以使用相同的技术重载Linq OrderBy扩展方法,这样无论您使用的是list.sort、ilist.sort还是ienumerable.orderby,都可以使用完全相同的语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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进行排序:
1 2 3 4 5 6 7 8 9 10 11 12 | 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/
如何使用Linq to对象为您排序?
假设你有一辆
1 2 3 | from c in list orderby c.Engine select c; |
编辑:在这里你需要快速得到答案。当我对其他答案提出稍微不同的语法时,我会留下我的答案——但是,给出的其他答案同样有效。
你必须做我认为类似的事情(把它转换成更具体的类型)。
也许把它放到一个t列表中,而不是数组列表中,这样就可以得到类型安全性和更多关于如何实现比较器的选项。
@davidmills的回答很好,但我认为可以改进。首先,当框架已经包含静态方法
此外,它还将
最后,重载的
下面的类为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 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]; } } } |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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)); } |
这里的想法是利用底层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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));** |
用于网格排序此方法根据属性名对列表进行排序。如下面的例子所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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(); } } } |
我在寻找原始文章中描述的确切问题的解决方案时发现了这个线程。然而,没有一个答案完全符合我的情况。布罗迪的回答非常接近。这是我的情况和解决办法。
我有两个同类型的ilist由nhibernate返回,并将这两个ilist合并为一个,因此需要进行排序。
就像布罗迪说的,我在对象(reportformat)上实现了一个ICompare,它是我的IList类型:
1 2 3 4 5 6 7 | public class FormatCcdeSorter:IComparer<ReportFormat> { public int Compare(ReportFormat x, ReportFormat y) { return x.FormatCode.CompareTo(y.FormatCode); } } |
然后,我将合并的IList转换为相同类型的数组:
1 |
然后对数组进行排序:
1 |
由于一维数组实现了接口
将您的
这是有效的解决方案吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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(); |
结果是:伊利斯特乙一C
表一乙C
再次重申一乙C
1 2 3 4 | using System.Linq; var yourList = SomeDAO.GetRandomThings(); yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) ); |
太漂亮了!贫民窟
找到了一个很好的帖子,我想分享一下。在这里看看
基本上。
可以创建以下类和IComparer类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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,你可以这样排序。
1 2 3 4 5 6 7 |
但要查看更多信息,请访问此网站…在这里看看
在VS2008中,当我单击服务引用并选择"配置服务引用"时,有一个选项可以选择客户端如何反序列化从服务返回的列表。
值得注意的是,我可以在System.Array、System.Collections.ArrayList和System.Collections.Generic.List之间进行选择。
下面是一个使用强类型的例子。但不确定这是否是最好的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Cast函数只是作为普通静态方法编写的3.5附带的扩展方法的一个重新实现。不幸的是,它非常丑陋和冗长。