Reputation: 15673
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
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)
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
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.The value that results from running the "reducer" callback function to completion over the entire array.
ref:
Upvotes: 4
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
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
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)
Upvotes: 8
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