2014-02-04 4 views
2

У меня есть класс с двумя свойствами, Name и Position. Я хотел бы заказать список с этим классом по позиции, а элементы с одинаковой позицией следует заказать по имени. Я работаю над статическим списком, поэтому я хотел бы работать на месте.Заказ списка на месте по двум свойствам

До сих пор мне удалось упорядочить список по одному свойству:

list.Sort((x, y) => x.Position.CompareTo(y.Position)); 

этот код работает, и у меня есть список упорядоченный по позиции, но я не знаю, как реализовать вторую часть. Я нашел this вопрос, но я не понимаю ответа.

Может ли кто-нибудь помочь мне?

ответ

0

Ответ вы связаны правильно. Ключ в сортировке по нескольким значениям состоит в том, что вторичное свойство имеет значение только в том случае, если первичные значения равны. Реализация psuedocode вашего сравнения сортировки может быть:

compare x and y position 
if they differ, return order 
else compare name, return order 

О методе Sort код после (x,y)=> должен возвращать 0, если элементы равны, отрицательное число, если первый должен быть перед вторым, и положительное число, если второе должно быть до первого. Метод CompareTo будет возвращать -1, 0 или 1 на основе этих случаев и аргументов. Поскольку вам нужно сравнить два разных свойства, вам необходимо два вызова CompareTo. Если вы решили добавить их вместе, вы могли бы иметь дело так:

  • x.position < y.position (сравните возвращает -1)
  • x.name> y.name (сравните возвращается 1)
  • результат 0, считаются равными, где ваши правила ясно говорят, что x должен быть первым в этом случае.

Для решения этой проблемы нам необходимо убедиться, что сравнение имен имеет значение, когда позиции равны. Так как CompareTo возвращает только -1, 0 или 1, если мы умножим результат позиции на 2 (или любое большее число), тогда сравнение по имени изменит результат только в том случае, если позиции равны. (Потому что -2 + 1 = -1 и 2 - 1 = 1)

Таким образом, используя метод, описанный в исходной связанный ответ, ваш код будет что-то вроде:

list.Sort((x, y) => 
    2 * x.Position.CompareTo(y.Position) 
    + x.Name.CompareTo(y.Name)); 
+0

@ Хамма: Надеюсь, это поможет вам понять, почему существует размножение. Вы также должны рассмотреть ответ Рене Хильгерса. Он создает новый список, но если вы делаете этот сорт много раз, а ваш список довольно велик, и вы пытаетесь избежать GC, вам, вероятно, не нужно беспокоиться о создании нового списка для этого типа. – mao47

+1

Я работаю с разными потоками, которые одновременно открывают и изменяют список через блокировки, поэтому моя задача - сделать операции как можно быстрее и эффективнее. Я понимаю, что умножение - это дать иерархию двум свойствам. – Hamma

0
list = list.OrderBy(item => item.Name).ToList(); 
list.Sort((x, y) => x.Position.CompareTo(y.Position)); 
+0

Это неявно опирается на алгоритм подстилающей сортировки не изменять порядок одинаковых элементов. – mao47

4

Я хотел бы использовать "OrderBy" и "ThenBy":

IEnumerable<Person> orderedPersons = persons.OrderBy(item => item.Position) 
      .ThenBy(item => item.Name); 
+0

Это, безусловно, самый надежный способ сделать это. – Guilherme

+0

Это самый простой способ сортировки по 2 свойствам, но требует создания нового списка, который OP не хотел делать. (хотя есть несколько причин, по которым этот список нужен, список будет необходим - сэкономить на производительности, если список очень велик) – mao47

Смежные вопросы