5

I will start with an apology about my poor English. I will try to be as clear as I can. :)

I have a 3-dimensional array (just an array of 2-dimensional arrays). My goal is to take one of the 2-dimensional arrays, and rotate it 90° counterclockwise. It look like this:

[1|2|3]  
[4|5|6]
[7|8|9]  

I try to make it "rotate" like this:

[3|6|9]  
[2|5|8]  
[1|4|7]

I want to change the original array, so I figured that I need to create a copy of it so i will have a reference to work with. So, here is what I have done:

var temp = [];
var cube =  [
    [
        ['A', 'A', 'A'],
        ['A', 'A', 'A'],
        ['A', 'A', 'A']
    ], [
        ['B', 'B', 'B'],
        ['B', 'B', 'B'],
        ['B', 'B', 'B']
    ], [
        ['C', 'C', 'C'],
        ['C', 'C', 'C'],
        ['C', 'C', 'C']
    ], [
        ['D', 'D', 'D'],
        ['D', 'D', 'D'],
        ['D', 'D', 'D']
    ], [
        ['1', '2', '3'],
        ['4', '5', '6'],
        ['7', '8', '9']
    ], [
        ['F', 'F', 'F'],
        ['F', 'F', 'F'],
        ['F', 'F', 'F']
    ]
];

function CCW() {
    temp = temp.concat(cube[4]);
    for(var i = 0; i < 3; i++)
        for(var j = 0; j < 3; j++)
            cube[4][i][j] =  temp[j][2-i];
}

CCW();

The copy of the original array should be in temp.

Now, the problem is in this line: cube[4][i][j] = temp[j][2-i];. Instead of changing only the values of the array in cube, it changes also the values of temp. I tried to change temp = temp.concat(cube[4]); to temp = cube[4].slice(0); but it did not make any diffrence.

How can I fix that? Thank you all. :)

Michael Haddad
  • 4,085
  • 7
  • 42
  • 82
  • 1
    And what about `temp = temp.concat(cube[4].slice());`? – sp00m Aug 20 '14 at 15:35
  • 1
    @sp00m That will still cause `temp` to hold references to the same inner arrays inside of `cube[4]`, won't it? I'm not 100% sure, but I think you need to go one level deeper and copy the individual string values (e.g. with `cube[4][i].slice()` or simply one by one). – apsillers Aug 20 '14 at 15:40

2 Answers2

1

when you assign an array directly, it is a reference assignment in javascript. This means that any changes will be reflected in both. To copy an array, you will need to call array.slice().

note: this will still be an assignment on a multi-dimensional array, so you will need to write something recursive to copy an array that has more than one dimension (at any element, e.g. [1, 2, ['some', 'inner', 'array'], 3])

does this kind of clear things up?

edit: here's a deepCopyArray function, this needs to be exanded for arbitrary objects, though...

function deepCopyArray(arr) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++)
    {
        var a = arr[i], ele;
        if (a instanceof Array) //current element is an array...
            ele = deepCopyArray(a);
        else 
            ele = a;
        newArr.push(ele);
    }
    return newArr;
}
kirinthos
  • 452
  • 2
  • 9
  • Well, can you help me with that? I'm not sure I 100% understand you. I mean, I understand that when I assign an array directly, when I make changes, it changes both. But I didn't understand how to fix it. There is a simple way? – Michael Haddad Aug 20 '14 at 15:47
  • does this help answer your question? – kirinthos Aug 20 '14 at 18:17
  • Well, actually yes. I think I understand what you did, and I will try it, but the thing is that I use JS only to check my algorithm rapidly, and I will eventually convert it to C# where it is much easier to do such things, so I do not know if it worth doing such complex stuff. Is there a simpler way? Thanks a lot for your help. – Michael Haddad Aug 20 '14 at 20:00
  • c# uses references as well, so you will encounter a similar problem [SO deals with it](http://stackoverflow.com/questions/4054075/how-to-make-a-deep-copy-of-an-array-in-c) and there are definitely other ways to go about doing this, one would be to create a stateful iteration where you never clone anything and move one value at a time, remembering the value you just replaced and moving that value next – kirinthos Aug 20 '14 at 20:06
  • So if, for example, I use a simple `for` and copy one value at a time it should work? – Michael Haddad Aug 20 '14 at 20:21
  • 1
    primitive types in c# are copied by value, so with both js and c#, if you copy the lowest-level values one-by-one into the new array, it will work. (this is what that deepCopyArray function is doing, getting down to just an integer and copying one by one at each level in the multi-dimensional array. note: as i said, but since this affects both js and c#, if you copy objects/classes, this form of copy will break down because of the same reference problem.) – kirinthos Aug 20 '14 at 20:33
0

var temp = cube.slice()

Should do the trick just put it in a for loop for each row.

Eligijus
  • 634
  • 1
  • 6
  • 15