Blog - Title

The SkipLast Extension Method

The SkipLast Extension Method

  • Comments 4

When writing queries, just as you sometimes want to skip the first n items in a collection, on occasion you want to skip the last n items.  You could certain count the items remaining in the collection, and use the Take operator to take all but the last, but this would mean iterating the collection twice, and would result in uglier code.  This post presents the SkipLast Extension method, which allows you to skip the last n items.

This blog is inactive.
New blog: EricWhite.com/blog

Blog TOC
In the next post, I’m going to present an enhancement to LtxOpenXml classes, which use LINQ to XML to query Open XML documents, to allow you to write queries on tables within spreadsheet (XLSX) documents.  I needed SkipLast to implement this.

Here is the implementation of the extension method, and a couple of examples of its use:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
 
publicstaticclassMyExtensions
{
    publicstaticIEnumerable<T> SkipLast<T>(thisIEnumerable<T> source,
        int count)
    {
        Queue<T> saveList = newQueue<T>();
        int saved = 0;
        foreach (T item in source)
        {
            if (saved < count)
            {
                saveList.Enqueue(item);
                ++saved;
                continue;
            }
            saveList.Enqueue(item);
            yieldreturn saveList.Dequeue();
        }
        yieldbreak;
    }
}
 
classProgram
{
    staticvoid Main(string[] args)
    {
        int[] a = new[] { 1, 2, 3, 4, 5 };
        var b = a.SkipLast(2);
        foreach (var item in b)
            Console.WriteLine(item);
 
        List<string> c = newList<string>() {
            "one", "two", "three", "four", "five"
        };
        var d = c.Skip(1).SkipLast(1);
        foreach (var e in d)
            Console.WriteLine(e);
    }
}
 

This example outputs:

1
2
3
two
three
four
 

Code is attached.

Attachment: SkipLast.cs
Leave a Comment
  • Please add 3 and 5 and type the answer here:
  • Post
  • PingBack from http://blogs.msdn.com/ericwhite/archive/2008/10/20/eric-white-s-blog-s-table-of-contents.aspx

  • Would it be more appropriate to use a Queue<T>, rather than a List<T>?  The implementation would be

      Queue<T> saveList = new Queue<T>();

           int saved = 0;

           foreach (T item in source)

           {

               if (saved < count)

               {

                   saveList.Add(item);

                   ++saved;

                   continue;

               }

               saveList.Enque(item);

               yield return saveList.Deque();

           }

           yield break;

  • Ben,

    You are absolutely right, a Queue<T> is the better collection to use.  I've updated the post with a new implementation.

    Thanks, Eric

  • You can make it a bit more efficient with a few small changes:

           // presize the queue (+1 since we enq before we deq)

           Queue<T> saveList = new Queue<T>(count+1);  

           foreach (T item in source)

           {

               // we always enq. no sense wait till after the if()

               saveList.Enqueue(item);

               if (count-- > 0)

                   continue;

               yield return saveList.Dequeue();

           }

Page 1 of 1 (4 items)