Clonación de matrices multidimensionales

8

Quiero clonar una matriz multidimensional @aen una matriz @b.

He procedido de la manera más intuitiva y se me ocurrió lo siguiente:

    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;

y la impresión es:

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

¿Eso significa que las dos matrices @a y @b están unidas?

Preguntas:

  1. ¿Por qué la matriz @a está unida a la matriz @b? (¿Cuál es el propósito del método de clonación en esta situación? Sabemos que la clonación se comporta como la intención de las matrices unidimensionales)
  2. ¿Cómo puedo realmente clonar @a a @b (multidimensional)?
  3. ¿Cuál es la forma más eficiente (tiempo limitado) de hacer eso?
jakar
fuente

Respuestas:

10

Lo que tienes no es una matriz multidimensional, sino más bien una matriz de matrices. Como clonees poco profundo, solo copiará la matriz de nivel superior. En este caso, clonetambién es redundante, ya que la asignación a una matriz ya es una operación de copia.

Una solución simple es clonar cada una de las matrices anidadas:

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

Alternativamente, podría usar una matriz multidimensional real. La declaración se vería así:

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

Y luego la copia en otra matriz sería:

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

Las tareas también deben actualizarse para usar la sintaxis multidimensional:

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

Y finalmente, el resultado de esto:

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

Es como se desea:

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

Como limpieza final, también puede "verter" una secuencia conceptualmente infinita de 0s en la matriz para inicializarla:

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

Lo que significa que la estructura 3x3 no necesita ser replicada a la derecha.

Jonathan Worthington
fuente
OKAY. Entendido. Entonces, cuando trato de cambiar @a [0] [1], en realidad cambio el Escalar @a [0] (que es una matriz), en ese caso el segundo valor de la matriz. Y cuando cambio @b [1] [0] en realidad cambio el contenido escalar de @b [1]. Y debido a que el método de clonación hace una copia superficial de la matriz @a, ambas matrices @a y @b tienen como contenido los mismos 3 escalares que son matrices. ¡Es por eso que obtengo el mismo resultado cuando imprimo las dos matrices al final! ¿Es eso correcto?
jakar
2
@ikarpenis @Larry usa escalar ('s' minúscula) en el sentido de Wikipedia y Scalar('S' mayúscula) para referirse al contenedor escalar integrado estándar de Raku . A Scalarnunca es una matriz; pero puede contener (una referencia a) un Array. Una asignación @a[0][1] = ...no cambia el escalar o Scalar @a[0], y tampoco coloca un nuevo Arrayen el Scalarcontenedor @a[0]. Simplemente cambia el valor retenido en el 2do Scalaren el existente Arrayretenido en el Scalarlímite existente a @a[0].
raiph
5

@ay @bno están obligados . Simplemente contienen las mismas cosas. El cloneno se repite y solo clona la matriz externa.

Una forma de lograr lo que quieres sería

@b = @a.map: *.clone; 
Holli
fuente