2010-03-04 2 views
12

Как я могу выполнить сортировку по двум различным критериям?Сортировка по двум критериям: по возрастанию, int по возрастанию

К примеру, у меня есть человек, такие объекты, как:

Person со свойствами FirstName (строка), LastName и Rank (целое).

Пример данных, например, так:

Xavier Smith 1 
Alexander Smith 2 
Alexander Smith 1 
Bob  Hawke 2 

Он должен сортировать по FirstName по алфавиту, затем ранга, например, в результате чего:

Alexander Smith 1 
Alexander Smith 2 
Bob  Hawke 2 
Xavier Smith 1 

До сих пор, я попытался следующие, но это не работает должным образом:

peopleList является List<Person>

peopleList.Sort(new Comparison<Person>((x,y) => x.Rank.CompareTo(y.Rank))); 
peopleList.Sort(new Comparison<Person>((x, y) => string.Compare(x.Name, y.Name))); 

Благодаря

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

peopleList.OrderBy(person => person.FirstName).ThenBy(person => person.Rank).ToList(); 

Дал бы тот же самый список, который был бы правильно отсортирован, правильно?

ответ

18

LINQ подход

С помощью LINQ вы можете использовать OrderBy и ThenBy:

var result = peopleList.OrderBy(p => p.FirstName).ThenBy(p => p.Rank); 

Это возвращает IEnumerable<T>. Если вам действительно нужен List<T>, добавьте .ToList() в конце.

Если вы хотите использовать метод Sort, тогда вам нужно будет написать собственный сопоставитель.

EDIT: используя ToList(), возвращает новый список. Если вы хотите отсортировать существующий список, вы должны использовать метод Sort, который не возвращает список, а скорее работает с текущим списком (это метод void).

Сортировка/Comparer подход

Использование: list.Sort(new PersonComparer());

Вот код Comparer. Он был адаптирован из MSDN example, поэтому я рекомендую прочитать комментарии, которые они использовали, чтобы понять, почему он структурирован таким образом.

public class PersonComparer : IComparer<Person> 
{ 
    public int Compare(Person x, Person y) 
    { 
     if (x == null) 
     { 
      if (y == null) 
      { 
       return 0; 
      } 
      else 
      { 
       return -1; 
      } 
     } 
     else 
     { 
      if (y == null) 
      { 
       return 1; 
      } 
      else 
      { 
       int retval = x.FirstName.CompareTo(y.FirstName); 

       if (retval != 0) 
       { 
        return retval; 
       } 
       else 
       { 
        return x.Rank.CompareTo(y.Rank); 
       } 
      } 
     } 
    } 
} 
+0

Я действительно должен прочитать больше о LINQ, кажется, что моя жизнь становится намного проще! – baron

+0

@baron см. Мое редактирование, я прокомментировал ваш вопрос в недавнем редактировании. –

+0

@baron Я добавил компаратор, который можно использовать с 'Sort()'. –

3

Мне нравится ответ LINQ.Если это не вариант, вы всегда можете использовать

(x,y) => 2*string.Compare(x.Name,y.Name) + x.Rank.CompareTo(y.Rank) 

так, что строка сравнения всегда доминирует, если он не равен 0

3

Вы на самом деле были очень близки с в месте сортировки синтаксиса лямбда. Вы просто не хватает на то, что лямбды может быть заключен в их собственной области:

peopleList.Sort(new Comparison<Person>((x,y) => 
{ 
    int result = x.FirstName.CompareTo(y.FirstName); 
    return (result != 0) ? result : x.Rank.CompareTo(y.Rank); 
})); 

Это немного меньше усилий, чем писать свой собственный IComparer<Person>!

+0

ahhhh .... Спасибо! Знание, которое поможет с большим количеством моего существующего кода:) – baron

+0

@Aaronaught очень приятно, но вам нужно перевернуть сравнение. Сначала сравните FirstName, затем во второй части тройного сравнения Rank. –

+0

@Ahmad: Упс, помогает прочитать вопрос, а. Исправлено. – Aaronaught

5

Другие ответы кажутся более изящными, чем это, и они заставляют меня чувствовать себя как больше noob, однако если вы поймете, как это сделать, вы можете сортировать любой список в любом случае, не зная много чего , И нет необходимости писать целый новый класс (хотя запись класса сравнения может быть полезна, если вы сортируете другие похожие списки в других частях вашего кода).

peopleList.Sort((x, y) => 
    { 
     int compare = x.FirstName.CompareTo(y.FirstName); 
     if (compare != 0) 
      return compare; 

     compare = x.Rank.CompareTo(y.Rank); 
     if (compare != 0) 
      return compare; 

     return x.LastName.CompareTo(y.LastName); 
    }); 
Смежные вопросы