与List <> OrderBy Alphabetical Order类似,我们希望按一个元素排序,然后按另一个元素排序.我们希望实现功能相当于
SELECT * from Table ORDER BY x, y
我们有一个包含许多排序函数的类,我们没有问题按一个元素排序.
例如:
public class MyClass { public int x; public int y; } ListMyList; public void SortList() { MyList.Sort( MySortingFunction ); }
我们在列表中有以下内容:
Unsorted Sorted(x) Desired --------- --------- --------- ID x y ID x y ID x y [0] 0 1 [2] 0 2 [0] 0 1 [1] 1 1 [0] 0 1 [2] 0 2 [2] 0 2 [1] 1 1 [1] 1 1 [3] 1 2 [3] 1 2 [3] 1 2
稳定的排序将是更可取的,但不是必需的.适用于.Net 2.0的解决方案是受欢迎的.
对于.Net的版本,您可以使用LINQ OrderBy
和ThenBy
(或者ThenByDescending
如果需要):
using System.Linq; .... List() a; List b = a.OrderBy(x => x.x).ThenBy(x => x.y).ToList();
注意:对于.Net 2.0(或者如果你不能使用LINQ),请参阅Hans Passant对这个问题的回答.
请记住,如果比较所有成员,则不需要稳定的排序.根据要求,2.0解决方案可能如下所示:
public void SortList() { MyList.Sort(delegate(MyClass a, MyClass b) { int xdiff = a.x.CompareTo(b.x); if (xdiff != 0) return xdiff; else return a.y.CompareTo(b.y); }); }
请注意,此2.0解决方案仍然优于流行的3.5 Linq解决方案,它执行就地排序,并且没有Linq方法的O(n)存储要求.除非你更喜欢原始的List对象当然不受影响.
您需要实现IComparer接口. 这是一篇包含示例代码的好文章.
诀窍是实现稳定的排序.我创建了一个可以包含测试数据的Widget类:
public class Widget : IComparable { int x; int y; public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } public Widget(int argx, int argy) { x = argx; y = argy; } public int CompareTo(object obj) { int result = 1; if (obj != null && obj is Widget) { Widget w = obj as Widget; result = this.X.CompareTo(w.X); } return result; } static public int Compare(Widget x, Widget y) { int result = 1; if (x != null && y != null) { result = x.CompareTo(y); } return result; } }
我实现了IComparable,因此它可以通过List.Sort()进行不稳定的排序.
但是,我还实现了静态方法Compare,它可以作为委托传递给搜索方法.
我从C#411借用了这个插入排序方法:
public static void InsertionSort(IList list, Comparison comparison) { int count = list.Count; for (int j = 1; j < count; j++) { T key = list[j]; int i = j - 1; for (; i >= 0 && comparison(list[i], key) > 0; i--) { list[i + 1] = list[i]; } list[i + 1] = key; } }
您可以将它放在您在问题中提到的排序助手类中.
现在,使用它:
static void Main(string[] args) { Listwidgets = new List (); widgets.Add(new Widget(0, 1)); widgets.Add(new Widget(1, 1)); widgets.Add(new Widget(0, 2)); widgets.Add(new Widget(1, 2)); InsertionSort (widgets, Widget.Compare); foreach (Widget w in widgets) { Console.WriteLine(w.X + ":" + w.Y); } }
它输出:
0:1 0:2 1:1 1:2 Press any key to continue . . .
这可能会被一些匿名代表清理,但我会把它留给你.
编辑:NoBugz展示了匿名方法的力量...所以,考虑我的更老的学校:P