Googlebot
Googlebot

Reputation: 15673

How to get the previous and next elements of an array loop in JavaScript?

In a simple array loop of Javacript as

for (var i=0; i<array.length; i++) {

var previous=array[i-1];
var current=array[i];
var next=array[i+1];

}

I need to get the previous and next elements in an unlimited cycle. For example,

The previous element of the first element in the array is the array last element
The next element of the last element in the array is the array first element

What can be the most efficient way to do this. The only way I can think of is to check if the element is the first or last in the array in every round.

In fact, I hope to make the array a closed cycle somehow, rather than linear.

Upvotes: 40

Views: 108829

Answers (5)

Danish
Danish

Reputation: 1497

you need reduce; a built sweet function to get previous and next values of array

[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, currentIndex, array) {
  return previousValue + currentValue;
});

for more info about Reduce

Edit: add some function signatures and more info below

reduce(function (accumulator, currentValue) { /* … */ }, initialValue)
reduce(function (accumulator, currentValue, currentIndex) { /* … */ }, initialValue)
reduce(function (accumulator, currentValue, currentIndex, array) { /* … */ }, initialValue)

Parameters

  • accumulator - : The value resulting from the previous call to callbackFn. On first call, initialValue if specified, otherwise the value of array[0].

  • currentValue - : The value of the current element. On first call, the value of array[0] if an initialValue was specified, otherwise the value of array[1].

  • currentIndex - : The index position of currentValue in the array. On first call, 0 if initialValue was specified, otherwise 1.

  • array - : The array reduce() was called upon.

  • initialValue Optional

    • : A value to which accumulator is initialized the first time the callback is called. If initialValue is specified, callbackFn starts executing with the first value in the array as currentValue. If initialValue is not specified, accumulator is initialized to the first value in the array, and callbackFn starts executing with the second value in the array as currentValue. In this case, if the array is empty (so that there's no first value to return as accumulator), an error is thrown.

Return value

The value that results from running the "reducer" callback function to completion over the entire array.

ref:

Upvotes: 4

AlixaProDev
AlixaProDev

Reputation: 560

To make it simple.

for the next element in array:

 currentIndex= (currentIndex+1)%array.length;

for the previous element in array:

currentIndex= (currentIndex+array.length-1)%array.length;

Upvotes: 5

Paolo
Paolo

Reputation: 15827

as you're talking about "unlimited cycle" I assume your loop is something like that

var i = 0,
    l = array.length;

while( true ) // keep looping
{
    if(i >= l) i = 0;

    // the loop block

    if(/* something to cause the loop to end */) break; // <-- this let execution exit the loop immediately

    i+=1;
}

The most efficient way to achieve your goal is the naive one: checking

    var previous=array[i==0?array.length-1:i-1];
    var current=array[i];
    var next=array[i==array.length-1?0:i+1];

obviously cache the length of the array in a variable

var l = array.length;

and (better style) the "vars" out of the cycle

var previuos,
    current,
    next;

Note that if you are accessing the array read only there would be a faster (but somewhat strange) way:

l = array.length;
array[-1] = array[l-1]; // this is legal
array[l] = array[0];

for(i = 0; i < l; i++)
{
    previous = array[i-1];
    current = array[i];
    next = array[i+1];
}

// restore the array

array.pop(); 
array[-1] = null;

Upvotes: 20

sidonaldson
sidonaldson

Reputation: 25284

To add to @Denys answer - this is how you can create a reuseable function

var theArray = [0, 1, 2, 3, 4, 5];
var currentIndex = 0;

function getAtIndex(i) {
    if (i === 0) {
        return theArray[currentIndex];
    } else if (i < 0) {
        return theArray[(currentIndex + theArray.length + i) % theArray.length];
    } else if (i > 0) {
        return theArray[(currentIndex + i) % theArray.length];
    }
}

// usage
getAtIndex(-2)

// you can even go crazy and it still works
getAtIndex(500)

Demo jsfiddle

Upvotes: 8

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382092

Use modulus :

var len = array.length;

var current = array[i];
var previous = array[(i+len-1)%len];
var next = array[(i+1)%len];

Note the +len when getting the previous: the reason we need this is to avoid negative indexes, due to the way modulus works (very unfortunately, -x% is -(x%))

Upvotes: 92

Related Questions