简体   繁体   English

Linq使用IOrderedEnumerable的智能程度和位置

[英]How intelligent is Linq with IOrderedEnumerable and Where

so let's say I have an IEnumerable dates and I want to get the dates within a range. 因此,假设我有一个IEnumerable日期,并且我想获取一个范围内的日期。

Is Linq and IOrderedEnumerable intelligent enough to realize the ability to choose faster algorithms given that the dates are now ordered. Linq和IOrderedEnumerable是否足够智能,以实现现在已定日期的情况下选择更快算法的能力。

So consider this: 所以考虑一下:

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)

If isn't smart with this implementation, is there some other implementation that would make it smart? 如果这种实现方式不明智,那么还有其他实现方式可以使其变得智能吗?

No it's not smart enough to do that. 不,这样做不够聪明。 Enumerable.Where<TSource> takes a Func<TSource, bool>, not an Expression<Func<TSource, bool>> like Queryable.Where<TSource>. Enumerable.Where <TSource>需要一个Func <TSource,bool>,而不是像Queryable.Where <TSource>这样的Expression <Func <TSource,bool >>。 So you could do it with an IQueryable, but you'd need a query provider that can do that. 因此,您可以使用IQueryable来做到这一点,但是您需要一个可以做到这一点的查询提供程序。 It's probably not worth the trouble. 这可能不值得麻烦。

However, something like this should do: 但是,应该执行以下操作:

orderedDates
    .SkipWhile(x => x.datetime1 < afterDateTime)
    .TakeWhile(x => x.datetime2 > beforeDateTime)

No; 没有; the Where operator has no idea what your predicate does; Where运算符不知道您的谓词做什么; it just knows to invoke a delegate that tells it whether to include an item in the result set. 它只知道调用一个委托,该委托告诉它是否在结果集中包括一个项目。 It would be possible for a query provider to do this with IOrderedQueryable , as the query provider would be able to analyze the expression tree. 查询提供程序可以使用IOrderedQueryable进行此IOrderedQueryable ,因为查询提供程序将能够分析表达式树。 I do not know if any query providers actually do that kind of analysis. 我不知道是否有任何查询提供者实际上进行了这种分析。

No. Where extension method does simple, linear search over all items in your collection and returns element if it follows your predicate. 不会。 Where扩展方法可以对集合中的所有项目进行简单的线性搜索,并在其谓词之后返回元素。 You can think of it as: 您可以将其视为:

foreach(var item in source)
    if(predicate(item))
        yield return item;

LINQ-to-objects works with delegates and treats them as blackboxes. LINQ到对象与委托一起使用,并将其视为黑盒。 So it does not know that your where condition has any relation to the earlier ordering operation. 因此,它不知道您的where条件与先前的订购操作有任何关系。 So it does not perform this optimization. 因此它不会执行此优化。

It's even worse than that, the sorting will be done each time you evaluate the query, even if it's shared. 甚至比这更糟糕的是,即使您是共享查询,每次您对查询进行排序时都会进行排序。 You need to materialize it with ToArray or ToList . 您需要使用ToArrayToList实现它。 Then you can use the built-in binary search function to speed this up. 然后,您可以使用内置的二进制搜索功能来加快速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM