LINQ - The Take and Skip methods

 

LINQ - The Take and Skip methods

The partitioning LINQ methods are used to fetch or skip elements from the beginning of an enumerable list while a condition yields true. The Take and Skip methods, and TakeWhile and SkipWhile methods, are complements of one another, meaning that if we concatenate the results from any of these two functional complements we will end up with the same sequence that we started with. These methods are available from .NET Framework 3.5 and onwards.

These are the variations of the four methods that we will be looking at in this article.

  • Take<T>
  • The Take<T> Method with a Nested Query
  • TakeWhile<T>
  • TakeWhile<T> Indexed
  • Skip<T>
  • Skip<T> Nested
  • SkipWhile<T>
  • SkipWhile<T> Indexed

The Take<T> Method

The Take method is used to fetch items from the beginning of an enumerable sequence for as long as the limiting condition is true. The return value is an IEnumerable<T> containing the items satisfying the condition; and all necessary information needed to perform the action is stored inside the result. You can use the Take method as an extension method (instance method) on any object that is of type IEnumerable<T>.

Deferred execution is used when calling the Take method, which means that the query will not be executed until a foreach loop is used, or one of the GetEnumerator, ToList, ToArray or ToDictionary methods is called directly on the on the result.

If the number of items stated in the Take methods’ parenthesis is greater than the available number of items in the collection, all items will be returned. If the number of items stated is less than one an empty IEnumerable<T> is returned.

If the source collection is null, an ArgumentNullException exception will be thrown.

Let’s say we have a collection of Film objects from which we want fetch the first 3 films. The IEnumerable<T> collection is a List<Film> named films; after the Take method has been called the result would be of the System.Linq.Enumerable.TakeIterator< Film> type, which is an IEnumerable<T> sequence that you can continue to query; the result will be generated when the items are accessed, for instance in a foreach loop.

var result = films.Take(3);

If you prefer to use LINQ syntax, the following code would yield the same result.

var result = (

   from f in films

   select f

).Take(3);

 

Note that we don’t have to specify the Film type when calling the Take method, the pre-compiler will figure out the correct type automatically.

Using the sample data the query would return:

---------- TAKE ----------

Star Wars

The Hobbit

Mad Max

The Take<T> Method with a Nested Query

The Take method can be used on a nested LINQ query to fetch a pre-determined number of items. The following example fetches the first 3 films and their corresponding film studio; to achieve this we use a second LINQ query nested within the first query. We then use the Take method on the outer LINQ query and store the each of the films using instances of the ExtendedFilm class.

var result = (

   from f in films

   select new ExtendedFilm

   {

      Title = f.Title,

      Studio = (

         from s in filmStudios

         where s.ID == f.StudioID

         select s.Name).First(),

         Rank = f.Rank

   }

).Take(3);

 

Using the sample data the query would return:

---------- TAKE NESTED ----------

Star Wars           Lucas Arts

The Hobbit          MGM

Mad Max             MGM

The TakeWhile<T> Method

The TakeWhile method is used to fetch items from the beginning of an enumerable sequence for as long as the limiting Lambda expression yields true. The return value is an IEnumerable<T> containing the items satisfying the Lambda expression; and all necessary information needed to perform the action is stored inside the result.

Read the section on the Take method for more detailed information on the TakeWhile method.

Let’s say we have a collection of Film objects from which we want fetch all the films up to the film with the title “Mad Max”. The IEnumerable<T> collection is a List<Film> with the name films; after the TakeWhile method has been called the result would be of the System.Linq.Enumerable .TakeWhileIterator< Film> type, which is an IEnumerable<T> sequence that you can continue to query; the result will be generated when the items are accessed, for instance in a foreach loop.

var result = films.TakeWhile(f => f.Title != "Mad Max");

If you prefer to use LINQ syntax, the following code would yield the same result.

var result = (

   from f in films

   select f

).TakeWhile(f => f.Title != "Mad Max");

 

Using the sample data the query would return:

---------- TAKE WHILE ----------

Star Wars

The Hobbit

The TakeWhile<T> Method Indexed

The indexed TakeWhile method is used to fetch items from the beginning of an enumerable sequence for as long as the limiting Lambda (predicate) function yields true; the zero-based index that is passed into the function represents the position of the current item in the source sequence. The return value is an IEnumerable<T> containing the items satisfying the Lambda expression; and all necessary information needed to perform the action is stored inside the result.

Read the section on the Take method for more detailed information on the TakeWhile method.

The following sample code would return any film from the source sequence starting from the beginning for as long as the index is less than the StudioID.

var result = films.TakeWhile((f, index) => index < f.StudioID);

Using the sample data the query would return:

---------- TAKE WHILE INDEXED ----------

Star Wars

The Hobbit

The Skip<T> Method

The Skip method will skip a given number of items from the beginning of an enumerable sequence and return the remaining items from the sequence. The return value is an IEnumerable<T> containing the items satisfying the condition; and all necessary information needed to perform the action is stored inside the result. You can use the Skip method as an extension method (instance method) on any object that is of type IEnumerable<T>.

Deferred execution is used when calling the Skip method, which means that the query will not be executed until either a foreach loop is used, or one of the GetEnumerator, ToList, ToArray or ToDictionary methods is called directly on the on the result.

If the number of items stated in the Skip methods’ parenthesis is greater than the available number of items in the collection; an empty IEnumerable<T> will be returned. If the number of items stated is less than one all items will be returned.

If the source collection is null, an ArgumentNullException exception will be thrown.

Let’s say we have a collection of Film objects from which we want skip the first 3 films. The IEnumerable<T> collection is a List<Film> with the name films; after the Skip method has been called the result would be of the System.Linq.Enumerable.SkipIterator< Film> type, which is an IEnumerable<T> sequence that you can continue to query; the result will be generated when the items are accessed, for instance in a foreach loop.

var result = films.Skip(3);

If you prefer to use LINQ syntax, the following code would yield the same result.

var result = (

   from f in films

   select f

).Skip(3);

 

Note that we don’t have to specify the Film type when calling the Skip method, the pre-compiler will figure out the correct type automatically.

Using the sample data the query would return:

---------- SKIP ----------

Monsters Inc.

Toy Story

RoboCop

Captain Phillips            

The Skip<T> Method with a Nested Query

The Skip method can be used on a nested LINQ query to skip a number of items in the sequence and fetch the remaining items. The following example skips the first 3 items and fetches the remaining films and their corresponding film studio; we use a second LINQ query nested within the first query to fetch the studio name. We then use the Skip method on the outer LINQ query to skip the first 3 items and store the remaining films using instances of the ExtendedFilm class.

var result = (

   from f in films

   select new ExtendedFilm

   {

      Title = f.Title,

      Studio = (

         from s in filmStudios

         where s.ID == f.StudioID

         select s.Name).First(),

         Rank = f.Rank

   }

).Skip(3);

 

Using the sample data the query would return:

---------- SKIP NESTED ----------

Monsters Inc.       Pixar

Toy Story           Pixar

RoboCop             Sony Pictures

Captain Phillips    Sony Pictures

The SkipWhile<T> Method

The SkipWhile method skips items from the beginning of an enumerable sequence for as long as the limiting Lambda expression yields true; and returns the remaining items in the sequence. The return value is an IEnumerable<T> containing the item that made the Lambda expression yield false and all the remaining items in the sequence. All necessary information needed to perform the action is stored inside the result.

Read the section on the Skip method for more detailed information on the SkipWhile method.

Let’s say we have a collection of Film objects from which we want fetch all the films starting with “Mad Max”. The IEnumerable<T> collection is a List<Film> named films; after the SkipWhile method has been called the result would be of the System.Linq.Enumerable .SkipWhileIterator< Film> type, which is an IEnumerable<T> sequence that you can continue to query; the result will be generated when the items are accessed, for instance in a foreach loop.

var result = films.SkipWhile(f => f.Title != "Mad Max");

If you prefer to use LINQ syntax, the following code would yield the same result.

var result = (

   from f in films

   select f

).SkipWhile(f => f.Title != "Mad Max");

 

Using the sample data the query would return:

---------- SKIP WHILE ----------

Mad Max

Monsters Inc.

Toy Story

RoboCop

Captain Phillips

The SkipWhile<T> Method Indexed

The indexed SkipWhile method skips items from the beginning of an enumerable sequence for as long as the limiting Lambda (predicate) function yields true; the zero-based index that is passed into the function represents the position of the current item in the source sequence. The return value is an IEnumerable<T> containing the items that follows in the sequence including the item that makes the Lambda expression yield false.

Read the section on the Skip method for more detailed information on the SkipWhile method.

The following sample code would skip any film from the source sequence starting from the beginning of the sequence for as long as the index is less than the StudioID.

var result = films.SkipWhile((f, index) => index < f.StudioID);

Using the sample data the query would return:

---------- SKIP WHILE INDEXED ----------

Mad Max

Monsters Inc.

Toy Story

RoboCop

Captain Phillips

Example data

public List<Film> films = new List<Film>()

{

   new Film{Title="Star Wars",  StudioID=001, Rank = new List<double>

      {7.8, 5.6, 9.5}},

   new Film{Title="The Hobbit", StudioID=002, ActorID = 002, Rank = new List<double>

      {7.2, 6.6, 8.5}},

   new Film{Title="Mad Max", StudioID=002, ActorID = 001, Rank = new List<double>

      {6.8, 5.6, 9.0}},

   new Film{Title="Monsters Inc.", StudioID=003, Rank = new List<double>

      {7.8, 7.6, 9.2}},

   new Film{Title="Toy Story", StudioID=003, Rank = new List<double>

      {6.8, 6.6, 6.5}},

   new Film{Title="RoboCop", StudioID=005, Rank = new List<double>

      {7.6, 7.7, 7.5}},

   new Film{Title="Captain Phillips", StudioID=005, ActorID = 003,

      Rank = new List<double> {8.4, 8.5, 8.6}}

};

 

public List<FilmStudio> filmStudios = new List<FilmStudio>()

{

   new FilmStudio(){Name="Lucas Arts", ID=001},

   new FilmStudio(){Name="MGM", ID=002},

   new FilmStudio(){Name="Pixar", ID=003},

   new FilmStudio(){Name="HBO Films", ID=004},

   new FilmStudio(){Name="Sony Pictures", ID=005}           

};

Example Classes

class Film

{

   public string Title { get; set; }

   public int StudioID { get; set; }

   public int ActorID { get; set; }

   public List<double> Rank { get; set; }

}

 

class ExtendedFilm : Film

{

   public string Studio { get; set; }

}

 

class FilmStudio

{

   public string Name { get; set; }

   public int ID { get; set; }

}

 http://msdn.microsoft.com/en-us/library/bb503062(v=vs.110).aspx

In this article we will have a look at how we can fetch and skip elements from a collection of objects based on an index value or a Lambda expression that is passed to one of the either the Take or Skip method in a LINQ query.

We will also see how we can use TakeWhile and SkipWhile to filter the result using the index of the elements in the source sequence; we achieve this by using an inline Lambda function in the call to the methods.

Stay connected with news and updates!

Join our mailing list to receive the latest news and updates from our team.
Don't worry, your information will not be shared.

Subscribe
Close

50% Complete

Two Step

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.