LINQ Partitioning Operators - Take, TakeWhile, Skip & SkipWhile


Image by Julien Maculan on Unsplash

I. Introduction

If you have been programming for a while now or at least with somewhat experience. You’ll agree that loops are part of the basic construct of a certain programming language.

Like in the C# language we have the for loop, the do-while loop, the while loop, and the foreach loop.

However, there are times when loops are often difficult to understand or discern their intention simply by looking at it and the developer needs to set a breakpoint and step into the code to understand its purpose.

This is true even of simple, single loops and especially nested ones. Having several looping constructs within a project could be a good candidate to be replaced by the standard LINQ operators that result in shorter and more intuitive code.

That’s why in this article, we’ll be discussing the LINQ partition operators and I’ll be showing its non-LINQ equivalent code.

II. Background

With our code sample, I decided to use the xUnit project for us to check the results of the LINQ operator and its non-LINQ equivalent using the C# language.

I do recommend downloading the sample project before we go deep with each of the LINQ partition operators.

III. What are LINQ Partition Operators?

LINQ partition operators divide the provided sequence into portions and return one of the portions. In other words, partition operators assist you as a developer in separating and returning a piece of the result sets from a given sequence of collections.

Here are the 4 different types of partition operators: Take, TakeWhile, Skip, and SkipWhile.

IV. The Take Operator

Using the Take operator, you need to specify the number of elements that you want to select or take from a given collection.

But before we go and see an example of the Take operator.

Let’s first try to see how we’ll do this via non-LINQ syntax.

private readonly string[] carBrands = {
    "Toyota",
    "Honda",
    "BMW",
    "Lexus",
    "Ford",
    "Isuzu"
};
[Fact]
public void Test_Using_Take_Operator_NonLinq_Equivalent() {
    //let's get the first 4 cars within the collection.
    int firstFourCars = 4;
    var cars = new string[firstFourCars];
    //let's loop until we reach the first 4 cars
    for (int i = 0; i < firstFourCars; i++) {
        cars[i] = carBrands[i];
    }
    //we are expecting that getFirstForCars does have the following collections
    // { "Toyota", "Honda", "BMW", "Lexus" }
    Assert.Collection(cars, item => Assert.Equal("Toyota", item), item => Assert.Equal("Honda", item), item => Assert.Equal("BMW", item), item => Assert.Equal("Lexus", item));
}

Output

See the screenshot asserting the collection after executing the loop to get the expected results that we intended to do.

With our example above we used loops to get the first four cars that we intended to do.

However, using the LINQ syntax will be much more obvious when we want to extract the first four cars.

Let’s see the example below.

private readonly string[] carBrands = {
    "Toyota",
    "Honda",
    "BMW",
    "Lexus",
    "Ford",
    "Isuzu"
};
[Fact]
public void Test_Using_Take_Operator_Via_LinqEquivalent() {
    //let's get the first 4 cars within the collection.
    int firstFourCars = 4;
    var cars = carBrands.Take(firstFourCars).ToArray();
    //we are expecting that getFirstForCars does have the following collections
    // { "Toyota", "Honda", "BMW", "Lexus" }
    Assert.Collection(cars, item => Assert.Equal("Toyota", item), item => Assert.Equal("Honda", item), item => Assert.Equal("BMW", item), item => Assert.Equal("Lexus", item));
}

Output

See the screenshot asserting the collection after executing the Take operator to get the expected results we intended.

How about that, seems to be much easier to understand at first look and lesser code, right?

V. The TakeWhile Operator

Using the TakeWhile operator helps you as a developer to take elements from a collection as long as a given condition is true.

Again, before we go and see an example of the TakeWhile operator.

Let’s try to show how we’ll do this via non-LINQ syntax.

Let’s see the example below.

private readonly List < dynamic > carBrands2 = new() {
    new {
        Car = "Toyota", IsJapanese = true
    },
    new {
        Car = "Honda", IsJapanese = true
    },
    new {
        Car = "BMW", IsJapanese = false
    },
    new {
        Car = "Lexus", IsJapanese = true
    },
    new {
        Car = "Ford", IsJapanese = false
    },
    new {
        Car = "Isuzu", IsJapanese = true
    }
};
[Fact]
public void Test_Using_TakeWhile_Operator_NonLinq_Equivalent() {
    var japaneseCars = new List < dynamic > {};
    //as we loop through the collection let's get the Japanese car
    for (int i = 0; i < carBrands2.Count; i++) {
        if (carBrands2[i].IsJapanese) {
            //add the Japanese car
            japaneseCars.Add(carBrands2[i]);
        } else {
            break;
        }
    }
    //we are expecting that japaneseCars does have the following collections
    // { Car = "Toyota", IsJapanese = true },
    // { Car = "Honda", IsJapanese = true  }
    Assert.Collection(japaneseCars, item => Assert.Equal("Toyota", item.Car), item => Assert.Equal("Honda", item.Car));
}

Output

See the screenshot asserting the collection after executing the loop that behaves like a TakeWhile operator.

OK, now let’s try to use the LINQ syntax equivalent and it’s up to you to decide if it is much more obvious and easier to use.

Let’s see the example below.

private readonly List < dynamic > carBrands2 = new() {
    new {
        Car = "Toyota", IsJapanese = true
    },
    new {
        Car = "Honda", IsJapanese = true
    },
    new {
        Car = "BMW", IsJapanese = false
    },
    new {
        Car = "Lexus", IsJapanese = true
    },
    new {
        Car = "Ford", IsJapanese = false
    },
    new {
        Car = "Isuzu", IsJapanese = true
    }
};
[Fact]
public void Test_Using_TakeWhile_Operator_Via_LinqEquivalent() {
    var japaneseCars = new List < dynamic > {};
    // let's get the Japanese car
    japaneseCars = carBrands2.TakeWhile(item => item.IsJapanese).ToList();
    //we are expecting that japaneseCars does have the following collections
    // { Car = "Toyota", IsJapanese = true },
    // { Car = "Honda", IsJapanese = true  }
    Assert.Collection(japaneseCars, item => Assert.Equal("Toyota", item.Car), item => Assert.Equal("Honda", item.Car));
}

Output

See the screenshot asserting the collection after executing the TakeWhile operator to get the expected results we intended.

How I wish I had new Japanese Honda cars. 😊

How about that, seems cleaner, and easier to understand at first look.

Now, let’s move to the next operator, the Skip operator.

VI. The Skip Operator

Using the Skip operator you need to specify the number of elements that it will skip then it will select the remaining elements in a collection.

I know you’re excited to see the LINQ syntax and how it is used. But before that let’s see the Skip operator in action via non-LINQ syntax.

Let’s see the example below.

private readonly string[] carBrands = {
    "Toyota",
    "Honda",
    "BMW",
    "Lexus",
    "Ford",
    "Isuzu"
};
[Fact]
public void Test_Using_Skip_Operator_NonLinq_Equivalent() {
    //let's put here the elements after skipping the first four
    string[] remainingCars = new string[carBrands.Length - 4];
    //let's skip the first four of the collection by starting at 4th index.
    for (int i = 4, j = 0; i < carBrands.Length; i++, j++) {
        remainingCars[j] = carBrands[i];
    }
    //we are expecting that remainingCars does have the following collections
    // { "Ford", "Isuzu" }
    Assert.Collection(remainingCars, item => Assert.Equal("Ford", item), item => Assert.Equal("Isuzu", item));
}

Output

See the screenshot asserting the collection after executing the loop that behaves like a Skip operator.

OK, now let’s try to use the LINQ syntax equivalent.

Let’s see the example below.

private readonly string[] carBrands = {
    "Toyota",
    "Honda",
    "BMW",
    "Lexus",
    "Ford",
    "Isuzu"
};
[Fact]
public void Test_Using_Skip_Operator_Via_LinqEquivalent() {
    //let's put here the elements after skipping the first four using the Skip operator
    string[] remainingCars = carBrands.Skip(4).ToArray();
    //we are expecting that remainingCars does have the following collections
    // { "Ford", "Isuzu" }
    Assert.Collection(remainingCars, item => Assert.Equal("Ford", item), item => Assert.Equal("Isuzu", item));
}

Output

See the screenshot asserting the collection after executing the Skip operator to get the expected results we intended.

How about that, less code, and easier to understand at first look, isn’t it?

Now, let’s move to the next operator, the SkipWhile operator.

VII. The SkipWhile Operator

Using the SkipWhile operator helps you as a developer to skip elements from a collection if a given condition is true.

Once the condition is false, the operator starts to get the values. In other words, the remaining elements down the road won’t be skipped.

Let’s see the SkipWhile operator in action via non-LINQ syntax.

Let’s see the example below.

private readonly List < dynamic > carBrands2 = new() {
    new {
        Car = "Toyota", IsJapanese = true
    },
    new {
        Car = "Honda", IsJapanese = true
    },
    new {
        Car = "BMW", IsJapanese = false
    },
    new {
        Car = "Lexus", IsJapanese = true
    },
    new {
        Car = "Ford", IsJapanese = false
    },
    new {
        Car = "Isuzu", IsJapanese = true
    }
};
[Fact]
public void Test_Using_SkipWhile_Operator_NonLinq_Equivalent() {
    var carNonJapanese = new List < dynamic > {};
    bool pickupValues = false;
    for (int i = 0; i < carBrands2.Count; i++) {
        //let's skip the japanese cars and the collection haven't pickup a false condition
        if (carBrands2[i].IsJapanese && !pickupValues) {
            continue;
        } else {
            //once the condition is false start to add the values to the new collection
            carNonJapanese.Add(carBrands2[i]);
            pickupValues = true;
        }
    }
    Assert.Collection(carNonJapanese, item => Assert.Equal("BMW", item.Car), item => Assert.Equal("Lexus", item.Car), item => Assert.Equal("Ford", item.Car), item => Assert.Equal("Isuzu", item.Car));
}

Output

See the screenshot asserting the collection after executing the loop that behaves like a SkipWhile operator.

OK, now let’s try to use the LINQ syntax equivalent.

Let’s see the example below.

private readonly List < dynamic > carBrands2 = new() {
    new {
        Car = "Toyota", IsJapanese = true
    },
    new {
        Car = "Honda", IsJapanese = true
    },
    new {
        Car = "BMW", IsJapanese = false
    },
    new {
        Car = "Lexus", IsJapanese = true
    },
    new {
        Car = "Ford", IsJapanese = false
    },
    new {
        Car = "Isuzu", IsJapanese = true
    }
};
[Fact]
public void Test_Using_SkipWhile_Operator_Via_LinqEquivalent() {
    //skips elements as long as the condition is true once false it starts to add the next values
    var carNonJapanese = carBrands2.SkipWhile(item => item.IsJapanese).ToList();
    Assert.Collection(carNonJapanese, item => Assert.Equal("BMW", item.Car), item => Assert.Equal("Lexus", item.Car), item => Assert.Equal("Ford", item.Car), item => Assert.Equal("Isuzu", item.Car));
}

Output

See the screenshot asserting the collection after executing the SkipWhile operator.

VIII. Conclusion

In this post, we have discussed the LINQ partitioning operators such as Take, TakeWhile, Skip and SkipWhile and for us to appreciate these operators we have included their non-LINQ equivalent for every single one of them.

I hope you have enjoyed this article as much as I have enjoyed writing it.

Stay tuned for more and don't forget to download the attached project-source code.

Until next time, happy programming!