2010-03-04 103 views
12

如何對兩個不同的標準執行排序?按照兩個標準排序,字符串升序,int升序

例如,我有人對象像:

Person具有屬性FirstName(字符串),LastName,和Rank(INT)。

實施例的數據如下所示:

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

應該排序姓按字母順序,然後在等級,例如由此而來:

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

到目前爲止,我曾嘗試以下,但它不能正常工作:

peopleListList<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可以使用OrderByThenBy

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

這將返回一個IEnumerable<T>。如果你真的需要List<T>在最後加上.ToList()

如果你想使用Sort方法,那麼你需要編寫一個自定義比較器。

編輯:使用ToList()返回一個新列表。如果要對現有列表進行排序,則應使用Sort方法,該方法不返回列表,而是在當前列表上進行操作(它是void方法)。

排序/的Comparer方法

用途:list.Sort(new PersonComparer());

這裏的比較器代碼。它改編自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 2010-03-04 03:23:27

+0

@baron查看我的編輯,我在最近的編輯中對您的問題進行了評論。 – 2010-03-04 03:25:11

+0

@baron我添加了一個可以和'Sort()'一起使用的比較器。 – 2010-03-04 03:36:59

3

我喜歡LINQ的答案。如果這不是一種選擇,你總是可以使用

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

使帶子比較始終占主導地位,除非它等於0

3

你實際上是非常接近與就地分揀lambda語法。你只是缺少一個事實,即lambda表達式可以在自己的範圍被封閉:

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 2010-03-04 03:46:39

+0

@Aarounaught很好,但你需要翻轉比較。首先比較FirstName,然後在三元比較Rank的第二部分。 – 2010-03-04 03:47:40

+0

@Ahmad:哎呀,有助於閱讀問題呃。修正了。 – Aaronaught 2010-03-04 03:49:35

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); 
    });