-1

I'm trying to write a function that picks a random entry from a multidimensional array (myArray), saves it to a new variable (myTempArray) and updates the first entry with an id number (counter).

When I change the value of mytempArray[0][0][0] it updates the equivalent value in myArray as well. I don't want these values to change.

How do I stop this from happening? Is slice the wrong method to use? If so, how do I duplicate the original array entry so I can modify it and use elsewhere? Code is below:

var myArray = [
[[0, "Description 1", 0, 0, 1, 6, 0, 0, 0, true, 0]],
[[0, "Description 2", 0, 0, 1, 6, 0, 0, 0, true, 0]],
[[0, "Description 3", 0, 0, 1, 6, 0, 0, 0, true, 0]],
];

function randomNumber (min, max) {
return Math.floor((Math.random() * max) + min);
};

counter = 1;

function myfunction(){

myrand = randomNumber(0,myArray.length-1); 
mytempArray = myArray.slice(myrand,myrand+1);
mytempArray[0][0][0] = counter;
counter++;
};

myfunction();
6
  • Arrays are reference types. slice only does a shallow clone, the nested arrays are copied over to the new one by reference. Commented Dec 30, 2017 at 16:54
  • 1
    Take a look here for how to deep copy arrays. stackoverflow.com/questions/597588/… Commented Dec 30, 2017 at 16:56
  • Other than Object.assign() you also can use the ...[] spread operator. Commented Dec 30, 2017 at 17:08
  • 1
    @ThirueswaranRajagopalan: Both spread and rest are syntax, not operators. Commented Dec 30, 2017 at 17:11
  • 1
    @ThirueswaranRajagopalan ...and neither one does a deep clone. Commented Dec 30, 2017 at 17:12

1 Answer 1

0

Remember that slice only works at one level in your structure. If you want a deep copy, you have to implement that yourself.

function myfunction() {
    var myrand = randomNumber(0, myArray.length - 1);
    var mytempArray = myArray.slice(myrand, myrand + 1); // <== Only copies one level
    mytempArray[0] = mytempArray[0].slice();             // <== Copy the next
    mytempArray[0][0] = mytempArray[0][0].slice();       // <== And the next
    mytempArray[0][0][0] = counter;
    // Presumably do something with `mytempArray` or return it
    counter++;
}

See below for a couple of other changes I made in there.


A couple of side notes:

  • Unless you're declaring myrand and mytempArray somewhere you haven't shown, your code is falling prey to The Horror of Implicit Globals*. Be sure to declare your variables.
  • There's no need for a ; at the end of a function declaration (as opposed to a function expression). ; is a statement terminator. Declarations aren't statements.

* (that's a post on my anemic little blog)

Sign up to request clarification or add additional context in comments.

4 Comments

Assuming that the data is valid JSON, var deepCopy = JSON.parse(JSON.stringify(oldArray));.
@JaredSmith: I believe strongly that using stringify+parse to copy data is wrong on several levels. :-)
Well, the general-purpose alternative is to recursively copy the data structure. Which in JavaScript means either trampolining or keeping an explicit stack to avoid running out of memory. Or you could write a million one-off versions for specific data structures with all the duplication and bug-potential that implies. I don't think it's going to be 'right' no matter which way you slice it (pun intended).
thanks @T.J.Crowder that worked!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.