Pierre-Yves Legeay
Pierre-Yves Legeay

Reputation: 648

Issue copying shuffled arrays in another 2 dimensions array

Edit (Solved): It was just a misunderstanding on my part on how arrays work in JS. Thanks to Nicholas Tower for his answer.

Original post:

Title : Closure issue using a function in a for-loop to modify a 2 dimensions array.

I have an array with a set of strings (rotationsSet), and i want to fill another array with 8 shuffled versions of rotationsSet. My 2D array end up filled 8 times with the last randomized set of string.

I am new to web dev and JS, but from what i have read it seems to be a closure issue. I tried using a forEach loop instead of a for loop in the initShuffledSets function but ended with the same result.

var numberOfCubes = 8;
var rotationsSet = [
    'rotateX(90deg)',
    'rotateX(-90deg)',
    'rotateY(90deg)',
    'rotateY(-90deg)',
    'rotateX(180deg)'
    ];

var shuffledRotationsSets = Array(numberOfCubes).fill(['']);

// Fisher-Yates array shuffle
function shuffle(array) {
    for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1)); 
        [array[i], array[j]] = [array[j], array[i]]; 
    }
}

function initShuffledSets() {
    for (let z = 0; z < shuffledRotationsSets.length; z++) { 
        shuffledRotationsSets[z] = rotationsSet;
        shuffle(shuffledRotationsSets[z]);
    }
}

initShuffledSets();

A console.log in the for-loop show 8 differents array (which is what i want), while a console log outside the for-loop show 8 identical array corresponding with the last shuffled array.

Upvotes: 0

Views: 47

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84982

There's only one line of code where you create an array:

var rotationsSet = [
    'rotateX(90deg)',
    'rotateX(-90deg)',
    'rotateY(90deg)',
    'rotateY(-90deg)',
    'rotateX(180deg)'
];

Everything else is just referencing that exact same array. This line of code does not create a copy:

shuffledRotationsSets[z] = rotationsSet;

shuffledRotationsSets[0] and shuffledRotationsSets[1], and shuffledRotationSets[2], etc, are all the exact same array, just referenced in different ways. So later on when you start mutating the array by swapping its elements, anything that's referring to that array will "see" the change.

If you want independent arrays that can be mutated separately, you need to copy it. To create a copy, there are a couple options. You can use array.slice():

shuffledRotationsSets[z] = rotationsSet.slice();

Or you can create an array literal and spread the old array into it:

shuffledRotationsSets[z] = [...rotationsSet];

Upvotes: 1

Related Questions