在 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】:

最好的方法是实现IComparableIComparable<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(即 IEnumerable 对象),尽管从最初的问题来看似乎没什么大不了的。唯一真正的区别是它返回一个新对象(然后您必须使用 ToList() 将其转换为列表),而 List.Sort 对当前实例执行排序。 @Noldorin。是的,您使用 List.Sort(comparisson) 的建议可能会更快... 谢谢,我不知道 ThenBy。 这样更快 myList.Sort((x, y) => DateTime.Compare(x.Created, y.Created));【参考方案5】:

另一种选择是使用自定义比较器:

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 进行了测试。所以将方法添加到WinFormMain()。您至少需要System.LinqSystem.Generic.Collections 程序集。

    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# 中对对象列表进行排序的主要内容,如果未能解决你的问题,请参考以下文章

C#中对列表进行排序的方法[重复]

如何根据用户输入在 C# 中对对象数组进行排序?

在c#中对数组进行排序[关闭]

在 C# Windows 窗体中对字典进行排序[重复]

在 Flutter 中对 JSON 列表进行排序 [重复]

Python中对列表进行排序的方法都有哪些呢?