【问题标题】:Sort a list of dates using C#使用 C# 对日期列表进行排序
【发布时间】:2015-12-09 19:31:01
【问题描述】:

我得到了一个包含datetextfinished 属性的条目列表。

我想按date 对这个列表进行排序。日期格式如下:dd.mm.yyyy

如果我运行这段代码,结果会像什么都没发生一样混淆。怎么了?

这是我的代码:

// in the namespace
struct entry
{
    public string date;
    public string text;
    public bool finished;

    public entry(string _date, string _text, bool _finished)
    {
        date = _date;
        text = _text;
        finished = _finished;
    }
}

// in my class
List<entry> entrys = new List<entry>();

// ** fill the list with content **

// where i want to sort the list
entrys.Sort(delegate (entry x, entry y)
{
    string date1 = x.date;
    string date2 = y.date;

    // 0123456789
    // dd.mm.yyyy

    int day1 = Convert.ToInt32(date1.Substring(0, 2));
    int day2 = Convert.ToInt32(date2.Substring(0, 2));

    int month1 = Convert.ToInt32(date1.Substring(3, 2));
    int month2 = Convert.ToInt32(date2.Substring(3, 2));

    int year1 = Convert.ToInt32(date1.Substring(6, 4));
    int year2 = Convert.ToInt32(date2.Substring(6, 4));

    if (year1 > year2) return -1;
    if (month1 > month2) return -1;
    if (day1 > day2) return -1;

    return 1;
});

【问题讨论】:

  • 不是答案,但如果两者相等,您的方法永远不会返回 0
  • 如果 year1
  • 您使用字符串存储日期而不是日期类型的任何原因?可以为您与另一个日期进行数据比较。
  • 字符串类型的代码只是寻找错误的东西......(也完全遵循“字符串类型”的口头禅,你也不应该使用 bool)。 :) 对类型本身或至少在比较方法中使用正确的 DateTime 有什么问题?
  • 天哪,我只是愚蠢,我不知何故认为如果 year1 > year2 是假的,那 year1 !

标签: c# list sorting date


【解决方案1】:

此代码有效:

entrys.Sort(delegate (entry x, entry y)
        {
            string date1 = x.date;
            string date2 = y.date;

            // 0123456789
            // dd.mm.yyyy

            int day1 = Convert.ToInt32(date1.Substring(0, 2));
            int day2 = Convert.ToInt32(date2.Substring(0, 2));

            int month1 = Convert.ToInt32(date1.Substring(3, 2));
            int month2 = Convert.ToInt32(date2.Substring(3, 2));

            int year1 = Convert.ToInt32(date1.Substring(6, 4));
            int year2 = Convert.ToInt32(date2.Substring(6, 4));

            if (year1 > year2) return 1;
            if (year1 == year2 && month1 > month2) return 1;
            if (year1 == year2 && month1 == month2 && day1 > day2) return 1;

            return -1;
        });

【讨论】:

  • 这不是一个应该解决问题的方式。不必要地执行的字符串操作的数量太多了。忽略在 C#./.Net 中有处理日期值的确切类型的事实
  • 如果它们相等,这将交换两个日期。假设你有d1,d2,d3,d4。如果在排序时d2d3 相等,它将变为d1,d3,d2,d4,如果再次排序,它将变回d1,d2,d3,d4。因为没有 0 返回表示两个日期相等
  • 我建议您使用内置的.Net DateTime 类及其比较方法和功能。
  • @M.kazemAkhgary 返回 0 仅在 OP 正在寻找稳定排序时才真正重要,但由于 List&lt;T&gt;.Sort "此实现执行不稳定排序;" - 在这种特殊情况下无关紧要。
【解决方案2】:

您的日期字段应成为 DateTime。但是,如果出于某种原因您需要将其作为字符串,请执行以下操作:

首先,在条目结构中添加一个 GetDate 方法:

public DateTime GetDate()
{
    int day = Convert.ToInt32(date.Substring(0, 2));

    int month = Convert.ToInt32(date.Substring(3, 2));

    int year = Convert.ToInt32(date.Substring(6, 4));

    return new DateTime(year,month,day);
}

然后,在排序时使用以下内容:

entrys.Sort((x, y) => x.GetDate().CompareTo(y.GetDate()));

【讨论】:

    【解决方案3】:

    始终遵循 KISS(保持简单愚蠢)原则:

    entrys.Sort(delegate (entry x, entry y)
    {
        DateTime dt1 = DateTime.ParseExact(x.date, "dd.MM.yyyy", 
              CultureInfo.InvariantCulture);
        DateTime dt2 = DateTime.ParseExact(y.date, "dd.MM.yyyy", 
              CultureInfo.InvariantCulture);
    
        return DateTime.Compare(dt1, dt2);
    });
    

    【讨论】:

      【解决方案4】:

      你真的很难做到这一点:

      var entries = new List<entry>();
      // ** fill the list with content **
      
      entries = entries.OrderBy(e => DateTime.ParseExact(e.date, "dd.MM.yyyy", null)).ToList();
      

      有人想知道为什么您还没有将.date 属性作为DateTime 类型而不是字符串。

      【讨论】:

      • +1。最干净的解决方案 IMO。请注意,此答案使用 LINQ 的 OP,因此您应该将 using System.Linq; 添加到您的 using 语句中。
      【解决方案5】:

      如果计算机可以为您解析字符串,则无需手动解析:

      var provider = System.Globalization.CultureInfo.InvariantCulture;
      entrys.Sort((a, b) => 
          DateTime.ParseExact(a.date, "dd.MM.yyyy", provider)
              .CompareTo(DateTime.ParseExact(b.date, "dd.MM.yyyy", provider)));
      

      【讨论】:

        【解决方案6】:

        刚刚在LinqPad 中快速输入,想法是使用Linq OrdeBy 并在结构/类上定义一个get 属性以返回解析的DateTime。您可以使用TryPraseExact 来提高安全性。

        void Main()
        {
        var list = new List<Entity>{
            new Entity{TempDate = "25.10.2015", SomeData="data1"},
            new Entity{TempDate = "20.10.2015", SomeData="data2"},
            new Entity{TempDate = "26.10.2015", SomeData="data3"},
            new Entity{TempDate = "18.10.2015", SomeData="data4"}};
        
        list.Dump("Original");
        
        list.OrderBy(x => x.DateTimeParsed).Dump("Sorted");
        }
        
        public struct Entity
        {
        public string TempDate {get; set;}
        public DateTime DateTimeParsed{ get{ return DateTime.ParseExact(TempDate, "dd.mm.yyyy",CultureInfo.InvariantCulture); }}
        
        public string SomeData {get; set;}
        }
        

        传递DateTimeOffset 而不是字符串日期也是一个好主意

        【讨论】:

          猜你喜欢
          • 2015-04-01
          • 2020-10-25
          • 2019-06-18
          • 2013-01-18
          • 2020-06-02
          • 1970-01-01
          • 2014-05-20
          • 1970-01-01
          相关资源
          最近更新 更多