【问题标题】:C#: sort list of objects by DateTime property that is nullableC#:按可为空的 DateTime 属性对对象列表进行排序
【发布时间】:2013-11-01 18:40:49
【问题描述】:

我有一个对象列表:List<FakeObject> list = ...

每个对象都有一个 DateTime 属性,我们称之为“日期”

我想按此日期属性按降序对该列表进行排序。但是,当我尝试

list.Sort(new Comparison<FakeObject>((x, y) => DateTime.Compare(x.Date, y.Date)))

它抱怨是因为 Date 属性可以为空。

如何对这个列表进行排序,它将可以为空的日期视为 MAX DATE,所以它出现在顶部?对我来说,快速简单的替代方法是不要让 Date 字段为空,但我们假设现在这不是一个选项。

简而言之:如果 DateTime 可以为空,我如何按 DateTime 对对象列表进行排序?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    一种可能的方法可能是:

    list.Sort(new Comparison<FakeObject>((x, y) => 
        -DateTime.Compare(x.Date ?? DateTime.MaxValue,
            y.Date ?? DateTime.MaxValue)));
    

    更新:在 OP 编辑​​问题以进行澄清后修改为使用 MaxDate

    请注意,您可以通过任一方式(MinDateMaxDate)执行此操作。最重要的是,如果它是null,那么给它一些静态值来完成你想要的。

    【讨论】:

    • 这也是按降序排列日期?
    • @HenleyChiu,不,这不会对它进行排序DESC。为此,只需在末尾添加对 Reverse 的调用即可。
    • Sort降序会更有效:要么交换xy,要么在前面放一个-(或者-1 * ,如果你觉得更清楚的话)的DateTime.Compare。 (另外,正如所写,它不能编译。Sort 返回void,而不是列表)
    • @TimS.,现在这是一个有趣的方法。请验证我的编辑是否正确。
    【解决方案2】:

    如果您想将所有空日期转换为最大日期值,那么只需在您的函数中执行此操作即可。您可以使用 null coalesce 运算符来获得更简洁的语法:

    list.Sort((x, y) => 
        DateTime.Compare(x.Date ?? DateTime.MaxValue, y.Date ?? DateTime.MaxValue))
    

    【讨论】:

    • +1 我的朋友,我很高兴我的回答模仿了你的回答,真令人谦卑!
    【解决方案3】:

    如果您可以替换列表,而不是就地修改它,您可以使用 LINQ。

    list = list.OrderByDescending(x => x.Date ?? DateTime.MaxValue).ToList();
    

    【讨论】:

      【解决方案4】:

      在比较之前将空日期实例设置为 MAX 怎么样?

      list.ForEach(x => x.Date = x.Date ?? null : DateTime.Max : x.Date);
      

      ...接着调用您的比较..

      【讨论】:

      • 改变列表中的值这似乎是不可取的,他只是想在排序时将其用作有效值。
      • 啊..是的,够公平的!
      【解决方案5】:

      我会做这样的事情。

      首先,给定一个这样的类

      class Widget
      {
          public DateTime? DateCreated { get ; set ; }
      }
      

      我会编写一个自定义比较器,如下所示:

      class Widget
      {
        public DateTime? DateCreated { get ; set ; }
      }
      
      class WidgetComparer : IComparer<Widget> , IComparer<DateTime?>
      {
        public bool NullCollatesHigh { get ; private set ; }
        private WidgetComparer( bool nullCollatesHigh )
        {
          this.NullCollatesHigh = nullCollatesHigh ;
          return ;
        }
      
        public int Compare( Widget x , Widget y )
        {
          int cc ;
      
          if      ( x == null && y == null ) cc = 0 ;
          else if ( x != null && y != null ) cc = Compare( x.DateCreated , y.DateCreated ) ;
          else if ( NullCollatesHigh       ) cc = x == null ? +1 : -1 ;
          else                               cc = x == null ? -1 : +1 ;
      
          return cc ;
        }
        public int  Compare(DateTime? x, DateTime? y)
        {
          int cc ;
      
          if      ( x == null && y == null ) cc = 0 ;
          else if ( x != null && y != null ) cc = DateTime.Compare( x.Value , y.Value ) ;
          else if ( NullCollatesHigh       ) cc = x == null ? +1 : -1 ;
          else                               cc = x == null ? -1 : +1 ;
      
          return cc ;
        }
      
      }
      

      那就很简单了

      widgetList.Sort( new WidgetComparer( true/false ) ) ;
      

      true 指定将空值整理得高于其他任何值,false 指定将它们整理得低于其他任何值。

      【讨论】:

      • 我已经选择了一个答案......而且它只有 1 行,比你的要简单得多。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 2017-07-21
      相关资源
      最近更新 更多