Список С# <> Сортировать по x, тогда y
Аналогично List < gt; OrderBy Алфавитный порядок, мы хотим отсортировать по одному элементу, затем другому. мы хотим добиться функционального эквивалента
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, приветствуется.
Ответы
Ответ 1
Имейте в виду, что вам не нужен стабильный вид, если вы сравниваете всех участников. Решение 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. Если вы, конечно, не хотите, чтобы исходный объект List был нетронутым.
Ответ 2
Для версий .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 на этот вопрос.
Ответ 3
Вам необходимо реализовать интерфейс IComparer. Вот хороший пост с примером кода.
Ответ 4
Фокус в том, чтобы реализовать стабильный вид. Я создал класс 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, который может быть передан в качестве делегата для метода поиска.
Я использовал этот способ сортировки вставки из С# 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
Ответ 5
Это может помочь вам,
Как сортировать общий список С#
Ответ 6
У меня была проблема, когда 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)));