C# Skip vs SkipWhile

When the need is to skip N count of items in a list we can rely on LINQ extension Skip(int count)

BasicallySkip extension performs a loop and continue until intteration count greater then the given count. For example;

Let’s say we have list of strings and we want to skip first two,

What we do is (without using LINQ),

static void Main(string[] args)
{
      List<string> items = new List<string>() { "Berkay", "Yaylacı", "Developer", "com" };

      int count = 2;
      List<string> result = new List<string>();

      for (int i = count; i < items.Count; i++)
      { 
          result.Add(items[i]);
      }

      Console.WriteLine(String.Join(",", result.ToArray()));
      Console.ReadKey();
}

We have just gave our count as starting index, and basically we have skipped items with given count

We can use Skip() to shorten this,

static void Main(string[] args)
{
      List<string> items = new List<string>() { "Berkay", "Yaylacı", "Developer", "com" };
      List<string> result = items.Skip(2).ToList();
      Console.WriteLine(String.Join(",", result.ToArray()));
      Console.ReadKey();
}

We have an obvious winner!

Let’s increase number of items in the list (this time I need to use integer array to produce much more items) lets say 100.000 then 1.000.000

static void Main(string[] args)
{
    List<int> items = Enumerable.Repeat(0, 1000000).ToList();

    int count = 500;
    List<int> result = new List<int>();
    var stopWatch = Stopwatch.StartNew();

    for (int i = count; i < items.Count; i++)
    {
        result.Add(items[i]);
    }

    Console.WriteLine("TraditionalPerformance:" + stopWatch.Elapsed.TotalMilliseconds);

    stopWatch = Stopwatch.StartNew();
    List<int> result2 = items.Skip(count).ToList();
    Console.WriteLine("SkipPerformance:" + stopWatch.Elapsed.TotalMilliseconds);
    Console.ReadKey();
}

First 100.000 items result,

1.000.000 items result,

Over 1 Million items; Skip() performance is much more better then Traditional way.

Why for loop lost performance? Here is the performance result,

1.000.000 -> Allocation has been done at the beginning took much more time but getCount and getItem performances are increased

100.000 -> getCount and getItem performance are three times slower then 1 million allocated list.

Okay, we have strayed from our topic. Let’s continue with SkipWhile(),

They both have the same purpose. Skip some items depends on a condition. Skip() has one condition which is an integer count parameter.

But!SkipWhile() can take predicate as a parameter.

First let’s try with traditional way,

static void Main(string[] args)
{
      List<string> items = new List<string>() { "Berkay", "Yaylacı", "Developer", "com" };
      List<string> result = new List<string>();
      bool isFound = false;
      foreach(var item in items)
      {
          if (!item.Contains("c") && !isFound)
          {
             isFound = true;
             continue;
          }

          result.Add(item);
      }

     Console.WriteLine(string.Join(",", result));
}

With SkipWhile(),

static void Main(string[] args)
{
     List<string> items = new List<string>() { "Berkay", "Yaylacı", "Developer", "com" };
     List<string> result = items.SkipWhile(x=> !x.Contains("c")).ToList();
     Console.WriteLine(String.Join(",", result.ToArray()));
     Console.ReadKey();
}

Here, we gave condition to our SkipWhile() extension. What we have wrote here is:

SkipWhile(x=> !x.Contains(“c”)) => “Skip until a word contains C letter”.

1- It has skipped "Berkay" because there is no "C".

2- Then it came to “Yaylacı”.

3- SkipWhile method has ended because “Yaylacı” has C letter.