与List<> OrderBy Alphabetical Order类似,我们希望按一个元素排序,然后按另一个元素排序。我们希望实现
的功能等价物SELECT * from Table ORDER BY x, y
我们有一个包含许多排序功能的类,我们没有问题按一个元素排序 例如:
public class MyClass {
public int x;
public int y;
}
List<MyClass> MyList;
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的解决方案很受欢迎。
答案 0 :(得分:154)
对于.Net版本,您可以使用LINQ OrderBy
和ThenBy
(或ThenByDescending
,如果需要):
using System.Linq;
....
List<SomeClass>() a;
List<SomeClass> b = a.OrderBy(x => x.x).ThenBy(x => x.y).ToList();
注意:对于.Net 2.0(或者如果你不能使用LINQ),请参阅Hans Passant answer这个问题。
答案 1 :(得分:98)
请记住,如果比较所有成员,则不需要稳定的排序。根据要求,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对象当然不受影响。
答案 2 :(得分:7)
您需要实现IComparer界面。 Here's a good post示例代码。
答案 3 :(得分:5)
诀窍是实现稳定的排序。我创建了一个可以包含测试数据的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<T>(IList<T> list, Comparison<T> 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)
{
List<Widget> widgets = new List<Widget>();
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<Widget>(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
答案 4 :(得分:4)
这可能对你有帮助, How to Sort C# Generic List
答案 5 :(得分:1)
我有一个问题,OrderBy和ThenBy没有给我想要的结果(或者我只是不知道如何正确使用它们)。
我选择了一个list.Sort解决方案。
var data = (from o in database.Orders Where o.ClientId.Equals(clientId) select new {
OrderId = o.id,
OrderDate = o.orderDate,
OrderBoolean = (SomeClass.SomeFunction(o.orderBoolean) ? 1 : 0)
});
data.Sort((o1, o2) => (o2.OrderBoolean.CompareTo(o1.OrderBoolean) != 0
o2.OrderBoolean.CompareTo(o1.OrderBoolean) : o1.OrderDate.Value.CompareTo(o2.OrderDate.Value)));