2010-03-04 67 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); 
    });