23

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.length;
for(var i = 0; i<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?

9 Answers 9

54
+100

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
Sign up to request clarification or add additional context in comments.

5 Comments

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].
I don't get it. (Negative number as array length?) Could you rephrase what you are trying to point out?
Why not just let val = arr[Math.abs(i % n)]; ?
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.
@wwgoncalves, you made my day. People in the comments below are giving funny answers, but yours is the simplest and most effective.
15

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(","));

Comments

11

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('****')
}

Comments

3

how about this one-liner I made ?

var nextItem = (list.indexOf(currentItem) < list.length - 1)
                        ? list[list.indexOf(currentItem) + 1] : list[0];

Comments

2
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(','));
}

Comments

0

One line solution for "in place" circular shift:

const arr = ["A","B","C","D"];
arr.forEach((x,i,t) => {console.log(i,t); t.push(t.shift());});
console.log("end of cycle", arr); // control: cycled back to the original

logs:

0 Array ["A", "B", "C", "D"]
1 Array ["B", "C", "D", "A"]
2 Array ["C", "D", "A", "B"]
3 Array ["D", "A", "B", "C"]
"end of cycle" Array ["A", "B", "C", "D"]

If you want only the first 3 items, use:

arr.forEach((x,i,t) => {console.log(i,t.slice(0, 3)); t.push(t.shift());});

3 Comments

Do you think Circular List is a way to solve this question? stackoverflow.com/questions/62238342/…
@JoãoRamires You should use getTime/setTime for your own question. See my answer there stackoverflow.com/questions/62238342/…
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]?
0

Another solutions:

    var arr = ['A','B','C','D'];
    var nextVal = function (arr) {        
        return arr[( ( ( nextVal.counter < ( arr.length - 1 ) ) ? ++nextVal.counter : nextVal.counter=0  )   )];
    };

    for(var i=0;i<arr.length;i++){
        console.log(nextVal(arr)+','+nextVal(arr)+','+nextVal(arr));
    }

And based on Modulo :

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

var nextVal = function (arr, dir = 1) { 
        if ( dir < 0 ) { nextVal.counter--;}
        let i = (nextVal.counter % len + len) % len;  
        if ( dir > 0 ) { nextVal.counter++; }
        return arr[i];
};

nextVal.counter=0;
for(var i=0;i<arr.length;i++){
    console.log(nextVal(arr)+','+nextVal(arr)+','+nextVal(arr));
}

// in reverse 
console.log('-------------------');
nextVal.counter=0;
for(var i=0; i<10; i++) {
    console.log(nextVal(arr, -1)+','+nextVal(arr, -1)+','+nextVal(arr, -1));
}

Comments

0

You could get the sliced part from index and the rest of slicing from start, if necessary.

This appraoch does not mutate the array.

const
    getCircular = (array, size) => array.map((_, i, a) => [
        ...a.slice(i, i + size),
        ...a.slice(0, i + size < a.length ? 0 : i + size - array.length)
    ]);


console.log(getCircular(['A', 'B', 'C', 'D'], 3).map(a => a.join('')));
console.log(getCircular(['A', 'B', 'C', 'D'], 5).map(a => a.join('')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

We can simply achieve this by using Array.splice() method along with the Destructuring assignment

Live Demo :

// Input array.
let arr = ['A', 'B', 'C', 'D'];

// Finding the length of an array.
const len = arr.length;

// Iterattion based on array length. 
for(let i = 0; i < len; i++) {
    const splittedArr = arr.splice(0, 3);
    arr.push(splittedArr[0]);
    arr = [splittedArr[1], splittedArr[2], ...arr]
    console.log(splittedArr);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.