1

所以假设我有一个 IEnumerable 日期,我想获得一个范围内的日期。

鉴于日期现在已排序,Linq 和 IOrderedEnumerable 是否足够智能以实现选择更快算法的能力。

所以考虑一下:

IOrderedEnumerable<ObjectWith2DateTimes> orderedDates = dates.OrderBy(x => new Tuple(x.datetime1,x.datetime2));

...
this is called a bunch
...
    DateTime afterDateTime = (some datetime)
    DateTime beforeDateTime = (other datetime)
    yield return orderedDates.Where(x => x.datetime1 >= afterDateTime && x.datetime2 <= beforeDateTime)

如果这个实现不聪明,是否有其他实现可以让它变得聪明?

4

4 回答 4

5

不,这样做不够聪明。Enumerable.Where<TSource> 采用 Func<TSource, bool>,而不是像 Queryable.Where<TSource> 那样的 Expression<Func<TSource, bool>>。因此,您可以使用 IQueryable 来执行此操作,但您需要一个可以执行此操作的查询提供程序。这可能不值得麻烦。

但是,这样的事情应该这样做:

orderedDates
    .SkipWhile(x => x.datetime1 < afterDateTime)
    .TakeWhile(x => x.datetime2 > beforeDateTime)
于 2014-03-06T22:33:12.250 回答
1

不; Where操作员不知道你的谓词是做什么的;它只知道调用一个委托,告诉它是否在结果集中包含一个项目。查询提供程序可以使用 来执行此操作IOrderedQueryable,因为查询提供程序将能够分析表达式树。我不知道是否有任何查询提供者实际上进行了这种分析。

于 2014-03-06T22:25:46.840 回答
0

否。Where扩展方法对集合中的所有项目进行简单的线性搜索,如果元素遵循您的谓词,则返回元素。你可以把它想象成:

foreach(var item in source)
    if(predicate(item))
        yield return item;
于 2014-03-06T22:25:50.237 回答
0

LINQ-to-objects 与委托一起工作并将它们视为黑盒。所以它不知道你的 where 条件与之前的排序操作有任何关系。所以它不执行这个优化。

更糟糕的是,每次评估查询时都会进行排序,即使它是共享的。你需要用ToArrayor来实现它ToList。然后您可以使用内置的二进制搜索功能来加快速度。

于 2014-03-06T22:26:30.920 回答