【问题标题】:Sorting a List of objects in C#在 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”来表示努力!

标签: c# sorting class list


【解决方案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();”我该怎么办???我搜索了所有的 stackoverflow :)
    • @Parsa 您可以创建一个扩展方法,如下所述:stackoverflow.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));
            

            【讨论】:

              猜你喜欢
              • 2016-11-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-07-01
              • 2010-10-29
              • 1970-01-01
              相关资源
              最近更新 更多