如何根据两个不同的标准进行排序?
例如,我有人物对象,如:
Person
包含属性FirstName
(字符串),LastName
和Rank
(int)。
示例数据如下:
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();
会给出完全相同的列表,只是排序正确,对吗?
答案 0 :(得分:20)
LINQ方法
var result = peopleList.OrderBy(p => p.FirstName).ThenBy(p => p.Rank);
这将返回IEnumerable<T>
。如果您确实需要List<T>
在最后添加.ToList()
。
如果您想使用Sort
方法,那么您需要编写自定义比较器。
编辑:使用ToList()
返回一个新列表。如果要对现有列表进行排序,则应使用Sort
方法,该方法不返回列表,而是对当前列表进行操作(它是void
方法)。
排序/比较方法
使用: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);
}
}
}
}
}
答案 1 :(得分:6)
其他答案似乎比这更优雅,它们让我感觉更像是一个菜鸟,但是如果你理解如何排序,你可以在不知道任何事情的情况下以任何方式对任何类型的列表进行排序。并且不需要编写一个全新的类(尽管如果在代码的其他部分中对其他类似的列表进行排序,编写一个比较器类会很有用。)
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);
});
答案 2 :(得分:4)
您实际上非常接近就地排序lambda语法。你只是错过了lambdas可以包含在自己的范围内的事实:
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>
相比,它的努力要少一些!
答案 3 :(得分:3)
我喜欢LINQ的答案。如果这不是一个选项,你可以随时使用
(x,y) => 2*string.Compare(x.Name,y.Name) + x.Rank.CompareTo(y.Rank)
这样字符串比较总是占主导地位,除非它等于0