【问题标题】:Unexpected behavior with OrderBy [ Descending ]() and SkipWhile()OrderBy [ Descending ]() 和 SkipWhile() 的意外行为
【发布时间】:2013-05-30 05:23:20
【问题描述】:

我看到一些我很难理解的行为。给定DateTimes 的列表,我只想按降序选择过去一年中出现的日期。但是使用OrderBy()OrderByDescending()SkipWhile() 的行为……很奇怪。给定从今天开始的列表,包括过去 100 个月,如下所示:

List<DateTime> ldt = new List<DateTime>();
for (int i = 0; i < 100; i++)
{
    ldt.Add(DateTime.Now.AddMonths(-i));
}

我从以下代码开始:

ldt = ldt.OrderByDescending(date => date).
          SkipWhile(date => date <= DateTime.Now.AddYears(-1)).ToList();

这会正确排序列表,但不会跳过任何记录。所以为了好玩,我尝试了这个(跳过比今天更早的所有内容,即所有内容):

 ldt = ldt.OrderByDescending(date => date).
            SkipWhile(date => date <= DateTime.Now).ToList();

哪个有效。该列表为空。然后我尝试了以下方法(OrderBy 而不是 OrderByDescending):

ldt = ldt.OrderBy(date => date).
          SkipWhile(date => date <= DateTime.Now.AddYears(-1)).ToList(); 

这完全符合预期 - 列表已排序,日期已正确过滤。所以最终的结果是:

ldt = ldt.OrderBy(date => date).
          SkipWhile(date => date <= DateTime.Now.AddYears(-1)).ToList();
ldt = ldt.OrderByDescending(date => date).ToList();

跳过,然后重新排序。那么我错过了什么?为什么其中一些有效,而另一些则以不可预知的方式中断?我正在尝试做的正确一行命令是什么?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    基本上,您需要TakeWhile 而不是SkipWhile

    ldt = ldt.OrderByDescending(date => date)
             .TakeWhile(date => date > DateTime.Now)
             .ToList();
    

    在您使用OrderByDescending 之后,您要保留的条目是第一个 条目...而SkipWhile 假设您要丢弃一些条目,然后保留 剩下的。

    (或者您可以使用 Where 进行过滤,然后按照 Reed 的建议进行排序。两者都可以使用 Reed 的可能更有效。使用您认为更容易理解的任何一个。)

    当您对这样的事情感到困惑时,有时值得在一张纸上写下数据示例。计算出每一步之后的顺序是什么样的,然后下一步会做什么。

    【讨论】:

      【解决方案2】:

      我只想选择过去一年发生的日期

      您应该可以使用.Where,而不是使用SkipWhile

       ldt = ldt.Where(date => date.> DateTime.Now.AddYears(-1))
              .OrderByDescending(date => date).ToList();
      

      【讨论】:

      • .Where() 强制评估整个列表。因为他也需要排序,所以比较慢:)
      • @JoelCoehoorn 是的,但它也不需要预先对输入列表进行排序。不确定这是否得到保证。 (他的例子当然适用于 TakeWhile)
      • @JoelCoehoorn: Where 只会懒惰地强迫它。这样就减少了排序 - 只有 需要 排序的条目(因为它们被包含在内)才会被排序。如果您使用 OrderByDescending 后跟 TakeWhile (根据我的回答),它将对 everything 进行排序,然后找出需要保留的内容。更少的谓词调用,但更多的排序。
      • @JonSkeet 因为我们在这里调用 .ToList ,所以没有什么懒惰的。但好的一点是,在排序之前进行过滤可能会更快。
      • @JoelCoehoorn:所以无论哪种方式都没有什么懒惰的 - 我看不出你第一条评论的意义,除非你指出谓词将应用于更多项目(这是真的)。
      猜你喜欢
      • 1970-01-01
      • 2017-03-27
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多