LINQ: Implementing The SkipLastWhile Operator

LINQ Com C#

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

4 Responses to LINQ: Implementing The SkipLastWhile Operator

  • Alberto says:

    Hello Mr. Morgado,
    I have read a question of you in msdn about an issue with Linq and VS2k8…

    I am getting the memory access violation error:

    System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    Thread information:
    Thread ID: 5
    Thread account name: IIS APPPOOL\OpenSpanServerAppPool
    Is impersonating: False
    Stack trace: at System.Linq.Enumerable.WhereEnumerableIterator`1.Select[TResult](Func`2 selector)
    at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
    at System.Web.Mvc.MvcHandler.RemoveOptionalRoutingParameters()
    at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
    at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
    at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
    at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
    at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

    I am using NHibernate an my site is hosted in IIS with its own pool , DB is SQL Server 2005 sp3.

    Did you see something related to this issue?

  • paulo says:

    If I recall it correctly, it was due to a Visual Studio add-in. Running outside Visual Studio (thus, not using the add-in) worked fine.

    Are you having this problem just running from Visual Studio, or always?

  • Phil says:

    I found in my case that it was due to having the TypeMock Isolator add-in without a license. Disabling the add-in(s) and restarting VS solved my problems.

  • paulo says:

    I kind of was leaning myself towards TypeMock. But I have a valide license, though.