How to access array in circular manner in JavaScript

28,294

Solution 1

Try this:

var arr = ["A","B","C","D"];
for (var i=0, len=arr.length; i<len; i++) {
    alert(arr.slice(0, 3).join(","));
    arr.push(arr.shift());
}

Without mutating the array, it would be

for (var i=0, len=arr.length; i<len; i++) {
    var str = arr[i];
    for (var j=1; j<3; j++)
        str += ","+arr[(i+j)%len]; // you could push to an array as well
    alert(str);
}
// or
for (var i=0, len=arr.length; i<len; i++)
    alert(arr.slice(i, i+3).concat(arr.slice(0, Math.max(i+3-len, 0)).join(","));

Solution 2

Answering to the main question, someone can access an array in a circular manner using modular arithmetic. That can be achieved in JavaScript with the modulus operator (%) and a workaround.

Given an array arr of a length n and a value val stored in it that will be obtained through an access index i, the circular manner, and safer way, to access the array, disregarding the value and sign of i, would be:

let val = arr[(i % n + n) % n];

This little trick is necessary -- someone can not use the modulus result straightforwardly -- because JavaScript always evaluates a modulus operation as the remainder of the division between dividend (the first operand) and divisor (the second operand) disconsidering their signs but assigning to the remainder the sign of the dividend. That behavior does not always result in the desired "wrap around" effect of the modular arithmetic and could result in a wrong access of a negative position of the array.

References for more information:

  1. https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/what-is-modular-arithmetic
  2. https://en.wikipedia.org/wiki/Modular_arithmetic
  3. https://en.wikipedia.org/wiki/Modulo_operation
  4. https://dev.to/maurobringolf/a-neat-trick-to-compute-modulo-of-negative-numbers-111e

Solution 3

Simply using modulus operator you can access array in circular manner.

var arr = ['A', 'B', 'C', 'D'];

for (var i = 0, len = arr.length; i < len; i++) {
  for (var j = 0; j < 3; j++) {
    console.log(arr[(i + j) % len])
  }
  console.log('****')
}

Solution 4

for (var i = 0; i < arr.length; i++) {
    var subarr = [];
    for (var j = 0; j < 3; j++) {
        subarr.push(arr[(i+j) % arr.length]);
    }
    console.log(i + " - " + subarr.join(','));
}

Solution 5

how about this one-liner I made ?

var nextItem = (list.indexOf(currentItem) < list.length - 1)
                        ? list[list.indexOf(currentItem) + 1] : list[0];
Share:
28,294
Anshul
Author by

Anshul

Hello, I am Anshul from Bengaluru, India, currently working @ Navi.

Updated on February 23, 2021

Comments

  • Anshul
    Anshul about 3 years

    I have an array like [A,B,C,D]. I want to access that array within a for loop like as

    var arr = [A,B,C,D];
    
    var len = arr.len;
    for(var i = 0;i<arr.len;i++){
        0 - A,B,C
        1 - B,C,D
        2 - C,D,A
        3 - D,A,B
    }
    

    I want to access that like in JavaScript, any ideas?

  • João Ramires
    João Ramires almost 4 years
    Do you think Circular List is a way to solve this question? stackoverflow.com/questions/62238342/…
  • allez l'OM
    allez l'OM almost 4 years
    @JoãoRamires You should use getTime/setTime for your own question. See my answer there stackoverflow.com/questions/62238342/…
  • Garrett
    Garrett about 3 years
    OK. But this does not provide a wrap around slice of the source array. It also fails with negative numbers; e.g. [1,2,3] start = 1,` len = -3` => [2,1,3].
  • wwgoncalves
    wwgoncalves about 3 years
    I don't get it. (Negative number as array length?) Could you rephrase what you are trying to point out?
  • Mkdgs
    Mkdgs about 3 years
    Why not just let val = arr[Math.abs(i % n)]; ?
  • wwgoncalves
    wwgoncalves about 3 years
    Unfortunately that won't work for negative values of i. The result -- remainder of the division -- will be different from the result expected from modular arithmetic. For example in JS (-1 % 10 + 10) % 10 evaluates to 9, but Math.abs(-1 % 10) evaluates to 1.
  • Garrett
    Garrett about 3 years
    That approach creates an array for each shift. What if there was a function like slice that wraps around and takes a length, e.g. array.cirSlice(start, len). [1,3,4].cirSlice(3,5) results [4,1,3,4,1]?