We're trying to write a LINQ statement against a List<T>
that searches backwards from the end of that list for a condition, but which stops at a specified 'T' item.
For instance, if the list has 1000 items and the 'limit' item is at position 995 (index 994), then we only want to search the last six items for the test condition. We need this to be as high-performance as possible.
However, to use LINQ, the only way we know is to get the existing index of the 'limit' item, which is expensive, then run a Select with index over the entire source collection, which also is expensive, like this...
// Assume limitItem is of type Foo and sourceList is of type List<Foo>
var limitIndex = sourceList.IndexOf(limitItem);
var sourceListWithIndex = sourceList.Select( (Foo, Index) => new { Foo, Index } );
var fooWithIndex = sourceListWithIndex
.LastOrDefault(item =>
(item.Foo.SomTestValue == true)
&&
(item.Index >= limitIndex) );
So is there an easier way to tell Linq 'Stop enumerating if you've checked this item', or will I have to manually do it myself in an index-based loop and not use LINQ at all?
LINQ syntax is typically less efficient than a foreach loop. It's good to be aware of any performance tradeoff that might occur when you use LINQ to improve the readability of your code. And if you'd like to measure the performance difference, you can use a tool like BenchmarkDotNet to do so.
Returns the last element of a sequence, or a default value if no element is found.
In a query expression, the select clause specifies the type of values that will be produced when the query is executed. The result is based on the evaluation of all the previous clauses and on any expressions in the select clause itself. A query expression must terminate with either a select clause or a group clause.
Given a list of city names, we need to reverse the list of cities and this can be done using the reverse() method in LINQ. The Reverse() method reverses the sequence of the elements in the specified list. it is available in both Queryable and Enumerable classes.
You don't need any of that.
sourceList.Reverse()
.TakeWhile(o => o != limitItem)
.FirstOrDefault(o => ...);
Thanks to deferred execution (and assuming sourceList
implements IList<T>
), this will iterate part of the list exactly once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With