如何按 C# 中的特定字段对对象列表进行排序?
Posted
技术标签:
【中文标题】如何按 C# 中的特定字段对对象列表进行排序?【英文标题】:How to sort a list of objects by a specific field in C#? 【发布时间】:2009-08-19 18:34:40 【问题描述】:我有这门课:
public class StatInfo
public string contact;
public DateTime date;
public string action;
然后我有一个 StatInfo 列表,但我不确定如何根据日期字段对其进行排序。我应该使用排序方法吗?我应该创建自己的吗?
var _allStatInfo = new List<StatInfo>();
// adding lots of stuff in it
_allStatInfo.SortByDate???
无需编写大量代码(如果可能的话),最好的方法是什么?
谢谢
【问题讨论】:
等待 Jon Skeet 出现。他的 C# in Depth: What you need to master C# 2 and 3 在这方面有很大的篇幅。 太晚了!当我关于 C# 的一个问题没有得到 Jon Skeet 的回答时,我总是感到惊讶:) 标题错误。说“数组” 【参考方案1】:使用 LINQ:
var sortedList = _allStatInfo.OrderBy(si => si.date).ToList();
对原始列表进行排序:
_allStatInfo.Sort(new Comparison<StatInfo>((x, y) => DateTime.Compare(x.date, y.date)));
【讨论】:
谢谢,第二种方法奏效了。我不使用 LINQ,所以无法测试第二个。【参考方案2】:我知道你已经得到了答案,但是......
你可以通过将语句分成两半来避免一些丑陋:
Comparison<StatInfo> comparison = (x, y) => DateTime.Compare(x.date, y.date);
_allStatInfo.Sort(comparison);
您也可以考虑直接致电CompareTo
:
Comparison<StatInfo> comparison = (x, y) => x.date.CompareTo(y.date);
_allStatInfo.Sort(comparison);
您可以使用我的 ProjectionComparer
类创建一个 IComparer<T>
实现 -
它是MiscUtil 的一部分,我在底部添加了一个未注释的版本
这个答案。然后你会写:
_allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => x.date));
即使您使用的是 .NET 2.0,您仍然可以通过 LINQBridge 使用 LINQ。
这是第二个答案所需的 ProjectionComparer
类。前几个类实际上只是帮助泛型类型推断更好地工作。
public static class ProjectionComparer
public static ProjectionComparer<TSource, TKey> Create<TSource, TKey>
(Func<TSource, TKey> projection)
return new ProjectionComparer<TSource, TKey>(projection);
public static ProjectionComparer<TSource, TKey> Create<TSource, TKey>
(TSource ignored, Func<TSource, TKey> projection)
return new ProjectionComparer<TSource, TKey>(projection);
public static class ProjectionComparer<TSource>
public static ProjectionComparer<TSource, TKey> Create<TKey>
(Func<TSource, TKey> projection)
return new ProjectionComparer<TSource, TKey>(projection);
public class ProjectionComparer<TSource, TKey> : IComparer<TSource>
readonly Func<TSource, TKey> projection;
readonly IComparer<TKey> comparer;
public ProjectionComparer(Func<TSource, TKey> projection)
: this (projection, null)
public ProjectionComparer(Func<TSource, TKey> projection,
IComparer<TKey> comparer)
projection.ThrowIfNull("projection");
this.comparer = comparer ?? Comparer<TKey>.Default;
this.projection = projection;
public int Compare(TSource x, TSource y)
// Don't want to project from nullity
if (x==null && y==null)
return 0;
if (x==null)
return -1;
if (y==null)
return 1;
return comparer.Compare(projection(x), projection(y));
【讨论】:
哦,谢谢,就在我说我没有得到你关于 C# 问题的答案时 :) 我会接受 Ben 的答案,但我赞成你的答案,我相信它会在正下方 @Ben:如果我能帮上忙,我就是不喜欢那么多括号:) Jon,在您的Compare
方法中,真的需要空检查吗?这应该留给调用者。
@nawfal:我不这么认为。您希望能够通过foo => foo.Name
订购,而无需通过foo => foo == null ? null : foo.Name
IMO。
@JonSkeet 您提供的示例可以写得更好,但仅此而已。如果我们提供像Compute(int, string)
这样的方法作为投影,比如_allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => Compute(someInt, x)))
,其中x
的空值是完全可以接受的怎么办?如果必须完全通用,则应由投影自行决定是否抛出空引用异常或忽略空值。【参考方案3】:
为了说明 Robert C. Cartaino 的回答:
public class StatInfo : IComparable<StatInfo>
public string contact;
public DateTime date;
public string action;
public int CompareTo(StatInfo value)
return this.date.CompareTo(value.date);
var _allStatInfo = new List<StatInfo>();
// this now sorts by date
_allStatInfo.Sort();
这不是最通用的解决方案,但如果您只想按日期排序,则很好。而且,正如 Robert 所说,您始终可以通过将 IComparer 参数传递给 sort 方法来覆盖默认排序。
【讨论】:
谢谢。它并不真正适用于我的情况,因为我只会在这种特殊情况下按日期排序,但我会记住这一点以备后用 @marcgg:我的答案中的代码使按日期排序成为默认行为。因此,如果您只按日期排序,我认为这正是您想要的。【参考方案4】:使用 lambda 表达式将一对映射到一个比较:
_allStatInfo.Sort((x, y) => x.date - y.date);
【讨论】:
感谢您的回答,但我收到一个错误:无法将 lambda 表达式转换为类型 System.Collections.Generic.IComparer' 因为它不是委托类型跨度> 【参考方案5】:它对我有用ُSorting array of custom type using delegate
// sort array by name
Array.Sort(users, delegate(User user1, User user2)
return user1.Name.CompareTo(user2.Name);
);
// write array (output: Betty23 Lisa25 Susan20)
foreach (User user in users) Console.Write(user.Name + user.Age + " ");
【讨论】:
【参考方案6】:对于 DateTime,不需要比较。
_allStatInfo.OrderyBy(d => d.date);
或
_allStatInfo.OrderByDescending(d => d.Date);
【讨论】:
两种方法都返回列表,所以你需要 _allStatInfo = _allStatInfo.OrderBy(d => d.date).ToList(); 谢谢,如果我没记错的话,List 没有这样的功能 我猜这是 LINQ。我没有使用 LINQ以上是关于如何按 C# 中的特定字段对对象列表进行排序?的主要内容,如果未能解决你的问题,请参考以下文章
如何按 .NET 2.0 中的特定属性对列表进行排序? [复制]
如何按距离(以英里为单位)从 C# 中的给定纬度/经度对纬度/经度列表进行排序?
Android-java-如何按对象内的某个值对对象列表进行排序