LINQ: Implementing The SkipLastWhile Operator
Following my last posts (>)(>), in this post I’ll introduce the implementation of the SkipLastWhile operator.
The SkipLastWhile returns all but the last contiguous elements from a a sequence that satisfy the specified criteria and is implemented as the SkipLastWhile extension methods:
public static IEnumerable<TSource> SkipLastWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
public static IEnumerable<TSource> SkipLastWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
The implementation of these methods is very simple. We start with an empty buffer and buffer every item that satisfies the criteria implemented by a predicate. Whenever an item doesn’t satisfy the criteria, all buffered items are yield, the buffer is cleared and the the item that doesn’t satisfy the criteria is yield:
var buffer = new List<TSource>(); foreach (var item in source) { if (predicate(item)) { buffer.Add(item); } else { if (buffer.Count > 0) { foreach (var bufferedItem in buffer) { yield return bufferedItem; } buffer.Clear(); } yield return item; } }
The overload that takes in account the index of the item only differs in the call the predicate that implements the criteria:
var buffer = new List<TSource>(); var idx = 0; foreach (var item in source) { if (predicate(item, idx++)) { buffer.Add(item); } else { if (buffer.Count > 0) { foreach (var bufferedItem in buffer) { yield return bufferedItem; } buffer.Clear(); } yield return item; } }
You can find the complete implementation of this operator (and more) CodePlex project for LINQ utilities and operators: PauloMorgado.Linq