How to skip every 'w' th indexes in an array

Viewed 56

I have an array with 9 elements

{0,1,2,3,4,5,6,7,8}

I am trying to get an output like this {2,5,8} where it skips the 0,1 - 3,4 - and 6,7

Things I tried are using a continue inside a for loop but couldn't find a generic use case I think % won't be useful here. i.e. with n elements and pick every wth element.

Please help

2 Answers

Array:

int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };

Simple way with a for loop:

for (int i = 2; i < arr.Length; i += 3)
{
    Console.WriteLine(arr[i]);
}

Here we start at the first item we want (index 2) and then skip 3 each time we iterate the loop.


You could also use LINQ's Where with the remainder operator:

IEnumerable<int> ints = arr.Where((_, i) => (i + 1) % 3 == 0);

foreach (var val in ints)
{
    Console.WriteLine(val);
}

Here we use _ to discard the actual value because we don't need it, and we store its index in i. Because arrays start from 0 we need to add 1, but then we can check if the position is divisible by 3. Therefore we get a boolean result: is the position in the array divisible by 3 -> true/false. If this evaluates to true then the item will be passed on by the Where method, otherwise it will be skipped.

As an example, index 5 of the array holds the value 5. 5 + 1 is 6, and 6 can be divided evenly by 3, so there is no remainder, therefore 6 % 3 is 0. Because of that, we want to save the value.

P.S. Note that LINQ stands for Language INtegrated Query, and our IEnumerable<int> is a filtered view of arr, so changing a value in arr and running another foreach over ints would produce an updated result. This isn't really relevant to your question, but some beginners stumble on this, so just a heads up.

For fun, here's a generic solution that will work for any array of any type and any w: * See edit below for improved code

private T[] GetEveryNthElement<T>(T[] array, int n)
{
    return array.Select((elem, i) => new
                                     {
                                         IsNthElement = (i + 1) % n == 0,
                                         Element = elem
                                     })
                .Where(o => o.IsNthElement)
                .Select(o => o.Element)
                .ToArray();
}

Sample usage:

var arr = new[]
          {
              0,
              1,
              2,
              3,
              4,
              5,
              6,
              7,
              8
          };

Console.WriteLine(string.Join(", ", GetEveryNthElement(arr, 3)));

The non-LINQ version of that code would be this:

private T[] GetEveryNthElement<T>(T[] array, int n)
{
    var elements = new List<T>();

    for (var i = 0; i < array.Length; i++)
    {
        if ((i + 1) % n == 0)
        {
            elements.Add(array[i]);
        }
    }

    return elements.ToArray();
}

but this would be more efficient:

private T[] GetEveryNthElement<T>(T[] array, int n)
{
    var elements = new List<T>();

    for (var i = n - 1; i < array.Length; i += n)
    {
        elements.Add(array[i]);
    }

    return elements.ToArray();
}

EDIT: Although I've never used it before, I should have realised that there is an overload of Where that uses indexes too, just as the Select method I used does. That means that my original code could be simplified to this:

private T[] GetEveryNthElement<T>(T[] array, int n)
{
    return array.Where((elem, i) => (i + 1) % n == 0).ToArray();
}

As the elem value is no longer used, it can be a discard:

private T[] GetEveryNthElement<T>(T[] array, int n)
{
    return array.Where((_, i) => (i + 1) % n == 0).ToArray();
}
Related