Список C# сортировка по x, затем y
аналогично Список Порядок В Алфавитном Порядке, мы хотим отсортировать по одному элементу, затем по другому. мы хотим достичь функционального эквивалента
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 приветствуется.
6 ответов:
имейте в виду, что вам не нужна стабильная сортировка, если вы сравниваете все члены. Решение 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, оно выполняет сортировку на месте и не имеет требования к хранению O(n) подхода Linq. Конечно, если вы не предпочитаете, чтобы исходный объект списка был нетронутым.
для версий .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 на этот вопрос.
вам нужно реализовать IComparer интерфейс. вот хороший пост с примерами кода.
хитрость заключается в реализации стабильной сортировки. Я создал класс виджетов, который может содержать ваши тестовые данные:
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, поэтому он может быть нестабильно отсортирован по списку.Род.)(
однако, я также реализовал статический метод сравнения, который может быть передан в качестве делегата для метода поиска.
я позаимствовал этот метод сортировки вставками от 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 . . .
это, вероятно, может быть очищено с некоторыми анонимными делегатами, но я оставлю это на вас.
EDIT: и NoBugz демонстрирует мощь анонимных методов...Итак, рассмотрим добывать больше олдскул :П
Это может помочь вам, Как сортировать C# Generic List
У меня была проблема, когда OrderBy и ThenBy не дали мне желаемого результата (или я просто не знал, как правильно их использовать).
Я пошел со списком.Вроде решение что-то вроде этого.
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)));