'How can I get the next few elements in an array but jump back to the start when passing the last element?

Imagine I have the following simple array:

const myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"];

Now I want to get the next for instance 3 elements after "el5" (index 4). As you can see there are only 2 elements left in the array. When hitting the last index in the array I want to go back to the start and continue there.

This should be the expected output when the start is "el5" (index 4): ["el6", "el7", "el1"].

And this is what I've tried so far.

const myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"];
let output = [];

const followingElementsCount = 3;
let startIndex = myArr.findIndex(el => el === "el5") + 1;
let overflow = 0;
for (let i = 0; i < followingElementsCount; i++) {
  if (startIndex + i >= myArr.length) {
    startIndex = 0;
    overflow++;
  }

  output.push(myArr[startIndex + i + overflow]);
}

console.log(output);

I can't believe it but I'm not capable of solving this probably fairly simple problem.



Solution 1:[1]

Using modulo:

const myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"];
const followingElementsCount = 3;
const startIndex = myArr.findIndex(el => el === "el5") + 1;

let output = [];
for (let i = 0; i < followingElementsCount; i++) {
  output.push(myArr[(startIndex + i) % myArr.length]);
}

console.log(output);

Solution 2:[2]

I played around with your function quite a bit and the solution I came up with is far simpler than I would've guessed at first. You don't even need to use any overflow value. Just start your loop at the startIndex, loop until startIndex + followingElementsCount, and in each loop, push(myArr[i % myArr.length]).

Using the modulo operator does exactly what you're looking for natively. When the number exceeds the length of the array, it resets back to zero and starts over. This will work, even if you want to loop for 20 or 200 iterations or more.

const myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"];
let output = [];

const followingElementsCount = 3;
let startIndex = myArr.findIndex(el => el === "el5") + 1;
for (let i = startIndex; i < startIndex + followingElementsCount; i++) {
  output.push(myArr[i % myArr.length]);
}

console.log(output);

Solution 3:[3]

Here is my take on this.

const myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"]
const searchFrom = myArr.findIndex(el => el === "el5")
const searchNext = 3

let r = myArr.length - ((searchFrom+1)+searchNext)
let res
r < 0 ? res = [...myArr.slice(searchFrom+1), ...myArr.slice(0, Math.abs(r))] : res = myArr.slice(searchFrom+1)

console.log(res)

Solution 4:[4]

You should turn your array into cyclic. In functional languages like Haskell this is a breeze with the cycle [2, 5, 7] instruction which would give an infinite list like [2, 5, 7, 2, 5, 7, ...] for you to not bother about it's end. Since Haskell is lazy by nature, we don't care about a list being infinite.

So in JS you may easily mimic this nice functionality by turning the index modular on the length of the array. Accordingly a simple function is sufficient for an elegant solution.

function collectCyclicFromIndex(i,n,a){
  return Array.from({length:n}, (_,j) => a[(i+j)%a.length])
};
myArr = ["el1", "el2", "el3", "el4", "el5", "el6", "el7"];
console.log(collectCyclicFromIndex(5,3,myArr));
console.log(collectCyclicFromIndex(2,13,myArr));
.as-console-wrapper {
max-height: 100% !important
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Majed Badawi
Solution 2 Brandon McConnell
Solution 3 ikiK
Solution 4