在 C# 中对对象列表进行排序
Posted
技术标签:
【中文标题】在 C# 中对对象列表进行排序【英文标题】:Sorting a List of objects in C# 【发布时间】:2010-10-29 20:31:50 【问题描述】:public class CarSpecs
public String CarName get; set;
public String CarMaker get; set;
public DateTime CreationDate get; set;
这是一个列表,我正在尝试找出一种有效的方法来按汽车制造日期对该列表列表 CarList 进行排序,其中包含 6 个(或任何整数数量)汽车。我本来打算做冒泡排序,但那行得通吗?有什么帮助吗?
谢谢
【问题讨论】:
(题外话)自动属性有人吗? @Peter Lillevold - 这也是我的第一个想法。我很久没有写过“正常”属性(由我写的局部变量支持)。 (麦克知道:“public DateTime CreationDate get; set; ”在 C# 3.0 中是合法的) 嗯,我在编辑器中按 Alt-Enter 让 ReSharper 转换为自动属性……但什么也没发生。哦,编辑这样的代码示例被认为是不礼貌的吗?虽然在这种情况下有点冒险,因为我们不确定@Mike 是否使用 C# 3.0.. @Peter - 我可能只是让他的代码示例保持原样(因为他没有使用 3.0 的可能性仍然存在)。我想如果他决定要使用自动属性,他可以更改它。不过,我会给你一个“A”来表示努力! 【参考方案1】:List<T>
类对您来说很简单,因为它包含一个Sort
method。 (它使用 QuickSort 算法,而不是 Bubble Sort 算法,这通常更好。)更好的是,它有一个带 Comparison<T>
参数的重载,这意味着你可以传递一个 lambda 表达式并使事情变得非常简单。
试试这个:
CarList.Sort((x, y) => DateTime.Compare(x.CreationDate, y.CreationDate));
【讨论】:
@Eoin:这有点模棱两可,我承认。我仍然相信他的意思是“汽车制造日期”作为一个属性,指的是CreationDate
。
如何通过这种方法比较一个int数据类型?
是的,我也想知道 :) 你如何将 int 数据类型与 this 进行比较?【参考方案2】:
最好的方法是实现IComparable
或IComparable<T>
,然后调用List<T>.Sort()
。这将为您完成所有繁重的排序工作。
【讨论】:
+1 以对抗其他人所做的毫无意义的 -1。这个建议没有错。【参考方案3】:如果您追求一种有效的排序方式,我建议您不要使用冒泡排序,而是使用快速排序。这个页面对算法提供了相当好的解释:
http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=574
祝你好运!
【讨论】:
【参考方案4】:你可以使用 LINQ:
listOfCars.OrderBy(x => x.CreationDate);
编辑:使用这种方法,可以轻松添加更多排序列:
listOfCars.OrderBy(x => x.CreationDate).ThenBy(x => x.Make).ThenBy(x => x.Whatever);
【讨论】:
是的,这也可以。然而,它的性能会比使用 List.Sort 更差,因为它基于 LINQ(即 IEnumerableToList()
将其转换为列表),而 List.Sort 对当前实例执行排序。另一种选择是使用自定义比较器:
using System;
using System.Collections.Generic;
using System.Text;
namespace Yournamespace
class CarNameComparer : IComparer<Car>
#region IComparer<Car> Members
public int Compare(Car car1, Car car2)
int returnValue = 1;
if (car1 != null && car2 == null)
returnValue = 0;
else if (car1 == null && car2 != null)
returnValue = 0;
else if (car1 != null && car2 != null)
if (car1.CreationDate.Equals(car2.CreationDate))
returnValue = car1.Name.CompareTo(car2.Name);
else
returnValue = car2.CreationDate.CompareTo(car1.CreationDate);
return returnValue;
#endregion
你这样称呼:
yourCarlist.Sort(new CarNameComparer());
注意:我没有编译此代码,因此您可能需要删除拼写错误
编辑:修改它,以便比较器根据相关请求在创建日期进行比较。
【讨论】:
修改了我的答案以匹配您的评论。这是完全控制排序的方法。但在这种情况下,这可能太多了:-) 无论如何这都是一个很好的答案,因为它也可以翻译成其他语言。当您使用 linq 或 lambda 表达式时,您将自己困在 C# 中。 (虽然我现在很想不做太多事情,只使用 lambda 的 1 行 :) 我想使用和实现 IComparer 接口,不要写“yourCarlist.Sort(new CarNameComparer());” .就是这样:“yourCarlist.Sort();”我该怎么办???我搜索了所有的 *** :) @Parsa 您可以创建一个扩展方法,如下所述:***.com/questions/1827719/…【参考方案6】:我会避免编写自己的排序算法,但如果你还是要这样做,请查看http://www.sorting-algorithms.com/ 以了解不同排序算法的一些比较...
【讨论】:
【参考方案7】:我只会使用内置 List.Sort 方法。它使用平均运行时间为 O(n log n) 的 QuickSort 算法。
此代码应该适合您,我将您的属性更改为自动属性,并定义了一个静态 CompareCarSpecs 方法,该方法仅使用现有的 DateTime.CompareTo 方法。
class Program
static void Main(string[] args)
List<CarSpecs> cars = new List<CarSpecs>();
cars.Sort(CarSpecs.CompareCarSpecs);
public class CarSpecs
public string CarName get; set;
public string CarMaker get; set;
public DateTime CreationDate get; set;
public static int CompareCarSpecs(CarSpecs x, CarSpecs y)
return x.CreationDate.CompareTo(y.CreationDate);
希望这会有所帮助。
【讨论】:
如果您没有可用的 C# 3.0(即没有 lambda),这是一个很好的解决方案。【参考方案8】:如果您使用的是 2.0,以下讨论可能有用:C# List<> Sort by x then y
【讨论】:
【参考方案9】:把这里提到的一些部分放在一起。这在 C# 4.x 和 VS2010 中编译和工作。我用WinForm
进行了测试。所以将方法添加到WinForm
Main()
。您至少需要System.Linq
和System.Generic.Collection
s 程序集。
private void SortCars()
List<CarSpecs> cars = new List<CarSpecs>();
List<CarSpecs> carsSorted = new List<CarSpecs>();
cars.Add(new CarSpecs
CarName = "Y50",
CarMaker = "Ford",
CreationDate = new DateTime(2011, 4, 1),
);
cars.Add(new CarSpecs
CarName = "X25",
CarMaker = "Volvo",
CreationDate = new DateTime(2012, 3, 1),
);
cars.Add(new CarSpecs
CarName = "Z75",
CarMaker = "Datsun",
CreationDate = new DateTime(2010, 5, 1),
);
//More Comprehensive if needed
//cars.OrderBy(x => x.CreationDate).ThenBy(x => x.CarMaker).ThenBy(x => x.CarName);
carsSorted.AddRange(cars.OrderBy(x => x.CreationDate));
foreach (CarSpecs caritm in carsSorted)
MessageBox.Show("Name: " +caritm.CarName
+ "\r\nMaker: " +caritm.CarMaker
+ "\r\nCreationDate: " +caritm.CreationDate);
public class CarSpecs
public string CarName get; set;
public string CarMaker get; set;
public DateTime CreationDate get; set;
【讨论】:
【参考方案10】:如果您使用委托(也称为匿名方法),则不必实现任何 IComparer / IComparable 接口。
public static void Main(string[] args)
List<CarSpecs> list = new List<CarSpecs>();
list.Add(new CarSpecs("Focus", "Ford", new DateTime(2010,1, 2));
list.Add(new CarSpecs("Prius", "Toyota", new DateTime(2012,3, 3));
list.Add(new CarSpecs("Ram", "Dodge", new DateTime(2013, 10, 6));
list.Sort(delegate (CarSpecs first, CarSpecs second)
int returnValue = 1;
if((first != null & second != null))
if (first.CarName.Equals(second.CarName))
if (first.CarMaker.Equals(second.CarMaker))
returnValue = first.CreationDate.CompareTo(second.CreationDate);
else
returnValue = first.CarMaker.CompareTo(second.CarMaker);
else
returnValue = first.CarName.CompareTo(second.CarName);
return returnValue;
);
【讨论】:
【参考方案11】:为了扩展 Noldorin 的答案,可以使用 int 数据类型对列表进行排序:
listName.Sort((x, y) => x.CompareTo(y));
或者如果列表中有一个复杂的对象:
inventoryList.Sort((x, y) => x.stockNumber.CompareTo(y.stockNumber));
【讨论】:
以上是关于在 C# 中对对象列表进行排序的主要内容,如果未能解决你的问题,请参考以下文章