Search code examples
arrayscloneraku

Cloning multidimensional arrays


I want to clone a multidimensional array @a to an array @b.

I've proceeded with the most intuitive way and I came up with the following:

    my @a = [0, 0, 0], [0, 0, 0], [0, 0, 0];

    my @b = @a.clone;

    @a[0][1] = 1;
    @b[1][0] = 1;

    say '@a : ' ~ @a.gist;
    say '@b : ' ~ @b.gist;

and the print out is:

    @a : [[0 1 0] [1 0 0] [0 0 0]]
    @b : [[0 1 0] [1 0 0] [0 0 0]]

That means that the two arrays @a and @b are binded?

Questions:

  1. Why array @a is binded to array @b (What is the purpose of the clone method in this situation? We know that clone behave as intented for one-dimensional arrays)
  2. How can I really clone @a to @b (multidimensional)?
  3. Which is the most efficient way (time bounded) to do that?

Solution

  • What you have is not a multi-dimensional array, but rather an array of arrays. Since clone is shallow, it will just copy the top-level array. In this case, the clone is also redundant, since assignment into an array is already a copying operation.

    A simple fix is to clone each of the nested arrays:

    my @b = @a.map(*.clone);
    

    Alternatively, you could use a real multi-dimensional array. The declaration would look like this:

    my @a[3;3] = [0, 0, 0], [0, 0, 0], [0, 0, 0];
    

    And then the copying into another array would be:

    my @b[3;3] = @a;
    

    The assignments also need updating to use the multi-dimensional syntax:

    @a[0;1] = 1;
    @b[1;0] = 1;
    

    And finally, the result of this:

    say '@a : ' ~ @a.gist;
    say '@b : ' ~ @b.gist;
    

    Is as desired:

    @a : [[0 1 0] [0 0 0] [0 0 0]]
    @b : [[0 0 0] [1 0 0] [0 0 0]]
    

    As a final cleanup, you can also "pour" an conceptually infinite sequence of 0s into the array to initialize it:

    my @a[3;3] Z= 0 xx *;
    

    Which means that the 3x3 structure does not need to be replicated on the right.