1

so let's say I have an IEnumerable dates and I want to get the dates within a range.

Is Linq and IOrderedEnumerable intelligent enough to realize the ability to choose faster algorithms given that the dates are now ordered.

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?

Anders Miltner
  • 253
  • 3
  • 12

4 Answers4

5

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>. So you could do it with an IQueryable, but you'd need a query provider that can do that. It's probably not worth the trouble.

However, something like this should do:

orderedDates
    .SkipWhile(x => x.datetime1 < afterDateTime)
    .TakeWhile(x => x.datetime2 > beforeDateTime)
Hans
  • 2,230
  • 23
  • 23
  • Not as fast as some sort of cool searching thing, then expanding to the sides, but still better than a normal where, thanks a lot! – Anders Miltner Mar 06 '14 at 23:11
  • That still needs to do a linear search until it finds the start of the target range, it just doesn't need to search from the end of the target to the end of the list. – Loki Mar 06 '14 at 23:13
  • Agreed, but it's better than nothing. – Anders Miltner Mar 06 '14 at 23:21
1

No; the Where operator has no idea what your predicate does; 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. I do not know if any query providers actually do that kind of analysis.

Mike Strobel
  • 25,075
  • 57
  • 69
0

No. Where extension method does simple, linear search over all items in your collection and returns element if it follows your predicate. You can think of it as:

foreach(var item in source)
    if(predicate(item))
        yield return item;
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
0

LINQ-to-objects works with delegates and treats them as blackboxes. So it does not know that your where condition has any relation to the earlier ordering operation. 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. Then you can use the built-in binary search function to speed this up.

Loki
  • 421
  • 2
  • 4