Marius Schulz Front End Engineer

I recently started working on the 2.0.0 version of ExtraLINQ, a small class library that provides additional extension methods for working with .NET collections and sequences. This second major release sports some internal infrastructure changes, but also a variety of new extension methods.

The `TakeEvery` Method

One of the new extension methods is `TakeEvery`, which returns every n-th element of a given sequence. Let's use the following array of Fibonacci numbers as an example:

``````int[] fibonaccis = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 };
``````

Here's how you would use `TakeEvery` to select every other number from the array:

``````int[] everyOtherFibonacci = fibonaccis.TakeEvery(2).ToArray();
// [0, 1, 3, 8, 21, 55]
``````

Similarly, you can also select only every third number:

``````int[] everyThirdFibonacci = fibonaccis.TakeEvery(3).ToArray();
// [0, 2, 8, 34]
``````

You get the idea.

Ambiguity of "take every …"

As you can see, in both cases the first item `0` is returned, and from there every item that is offset by a multiple of `step`, the parameter passed to `TakeEvery`. In the first example, the indices of the selected items are 0, 2, 4, 6, 8, and 10.

That's not the only right way to interpret take every other item, though. In fact, I could have implemented `TakeEvery` to return all the items at indices 1, 3, 5, 7, and 9 instead, thus skipping the first `step-1` items. The resulting sequence would equal `[1, 2, 5, 13, 34]` in this case.

The decision I needed to make when writing the `TakeEvery` method was where to start the counting. In the end, I went with the first approach shown in the above code snippet because it nicely plays together with other LINQ methods.

If you want to select every other item starting at the second item (skip, take, skip, take, …) rather than the first one (take, skip, take, skip, …), you can combine `TakeEvery` with `Skip`, a basic building block of LINQ, to achieve the desired offset:

``````int[] everyOtherFibonacci = fibonaccis
.Skip(1)
.TakeEvery(2)
.ToArray();

// [1, 2, 5, 13, 34]
``````

Note that it wouldn't have worked the other way around. If the first item were always skipped by `TakeEvery`, neither `Skip` nor `Take` would include it in the resulting sequence.

Designing for Composition

I could also have added to the `TakeEvery` method another parameter named `offset` which specifies how many items to skip before starting the stepping. This, however, would have made the extension method more complicated than necessary.

Instead, I designed it for composition because there's already a method available out of the box (namely `Skip`) to achieve such an offset. Also, this makes understanding, implementing, and testing the method much easier.

The next time you have to choose between two alternatives like in the above example, opt for the one that allows for flexible functional composition with other logical units already available within your code.