I'm implementing a John Conway Game of Life, but I'm having a weird problem. Here is a short version if the code giving me trouble:
let lifeMap = [
[true, false, false],
[false, false, false],
[false, false, false]
];
let oldLifeMap = lifeMap.slice();
for (let row = 0; row < lifeMap.length; row++) {
for (let val = 0; val < lifeMap[row].length; val++) {
let bool = lifeMap[row][val];
let newBool = false; // here is where I would determine if cell is alive/dead
lifeMap[row][val] = newBool;
if (row === 0 && val === 0) console.log("at (0,0)", oldLifeMap[0][0]);
}
}
In response to this code, JavaScript prints at (0,0) false
. I need it to stay true
until the next generation starts.
I thought doing let oldLifeMap = lifeMap.slice()
would fix it, but it doesn't, and I'm not sure why. (Shouldn't it copy the 2d array and not create a second ref to it?)
Anyway, what is going on here, and how do I successfully make an actual copy of lifeMap
here?
I'm implementing a John Conway Game of Life, but I'm having a weird problem. Here is a short version if the code giving me trouble:
let lifeMap = [
[true, false, false],
[false, false, false],
[false, false, false]
];
let oldLifeMap = lifeMap.slice();
for (let row = 0; row < lifeMap.length; row++) {
for (let val = 0; val < lifeMap[row].length; val++) {
let bool = lifeMap[row][val];
let newBool = false; // here is where I would determine if cell is alive/dead
lifeMap[row][val] = newBool;
if (row === 0 && val === 0) console.log("at (0,0)", oldLifeMap[0][0]);
}
}
In response to this code, JavaScript prints at (0,0) false
. I need it to stay true
until the next generation starts.
I thought doing let oldLifeMap = lifeMap.slice()
would fix it, but it doesn't, and I'm not sure why. (Shouldn't it copy the 2d array and not create a second ref to it?)
Anyway, what is going on here, and how do I successfully make an actual copy of lifeMap
here?
- The outer array is a copy, but each inner array remains a reference. That is expected behavior from what you're doing. – Patrick Roberts Commented Aug 29, 2017 at 22:38
- gotcha. How do I make a deep copy then? – Andrew Horn Commented Aug 29, 2017 at 22:41
-
3
.map(a => a.slice())
– Patrick Roberts Commented Aug 29, 2017 at 22:43 - Possible duplicate of How do you clone an Array of Objects in Javascript? – abagshaw Commented Aug 29, 2017 at 22:43
-
1
var copy = JSON.parse(JSON.stringify(lifeMap))
– epascarello Commented Aug 29, 2017 at 22:48
2 Answers
Reset to default 13A hat-tip to @Redu's answer which is good for N-dimensional arrays, but in the case of 2D arrays specifically, is unnecessary. In order to deeply clone your particular 2D array, all you need to do is:
let oldLifeMap = lifeMap.map(inner => inner.slice())
This will create a copy of each inner array using .slice()
with no arguments, and store it to a copy of the outer array made using .map()
.
You may clone an ND (deeply nested) array as follows;
Array.prototype.clone = function(){
return this.map(e => Array.isArray(e) ? e.clone() : e);
};
or if you don't want to modify Array.prototype
you may simply refactor the above code like;
function cloneArray(a){
return a.map(e => Array.isArray(e) ? cloneArray(e) : e);
};