Podría confundirse con complejidades como ArrayObject, que es un objeto que actúa exactamente como una matriz. Sin embargo, al ser un objeto, tiene semántica de referencia.
Editar: @AndrewLarsson plantea un punto en los comentarios a continuación. PHP tiene una característica especial llamada "referencias". Son algo similares a los punteros en lenguajes como C / C ++, pero no son lo mismo. Si su matriz contiene referencias, mientras la matriz se pasa por copia, las referencias aún se resolverán en el objetivo original. Por supuesto, ese suele ser el comportamiento deseado, pero pensé que valía la pena mencionarlo.
No respondiste la pregunta. Solo explicaste el problema. Lo cual, para el OP, es muy probablemente lo que estaba buscando. Sin embargo, para mí (y para otros también), viniendo aquí casi cuatro años después con un problema similar, todavía no tengo una buena manera de clonar una matriz sin modificar la matriz original (que también incluye punteros internos). Supongo que es hora de que haga mi propia pregunta.
Andrew Larsson
28
@AndrewLarsson Pero PHP lo hace de manera predeterminada: eso es lo esencial. Sin embargo, las referencias no se resuelven, por lo que si necesita eso, tendrá que atravesar recursivamente la matriz y construir una nueva. Del mismo modo, si la matriz fuente contiene objetos y desea clonarlos, deberá hacerlo manualmente. Tenga en cuenta también que las referencias en PHP no son lo mismo que los punteros en C. Sin saber nada sobre su caso, puedo sugerir que es extraño tener una serie de referencias en el primer caso, especialmente si no tiene intención de tratar ellos como referencias? ¿Cuál es el caso de uso?
Pero, ¿qué pasa cuando no es el comportamiento deseado? La pregunta pregunta cómo hacer una copia profunda . Obviamente no es deseado. Su respuesta no es mejor que es: $copy = $original;. Lo que no funciona si los elementos de la matriz son referencias.
doug65536
8
Como siempre phpnos presenta el resultado menos esperado , porque esta solución no siempre funciona . $a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];imprime array0mientras $a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];imprime array1. Aparentemente, algunas matrices se copian por referencia.
Tino
186
PHP copiará la matriz por defecto. Las referencias en PHP deben ser explícitas.
$a = array(1,2);
$b = $a;// $b will be a different array
$c =&$a;// $c will be a reference to $a
Usar la referencia puede ser importante si la matriz es enorme. No estoy seguro, pero supongo que debería conducir a un menor consumo de memoria y un mejor rendimiento (no es necesario copiar toda la matriz en la memoria).
Robsch
11
@robsch: en el nivel de la lógica del programa, la matriz se copia. Pero en la memoria, en realidad no se copiará hasta que se modifique, porque PHP usa semántica de copia en escritura para todos los tipos. stackoverflow.com/questions/11074970/…
Jessica Knight
@CoreyKnight Es bueno saberlo. Gracias por esto.
robsch
44
tenga en cuenta que esto no es cierto para las matrices anidadas, son referencias y, por lo tanto, termina con un desastre roto
MightyPork
45
Si tiene una matriz que contiene objetos, debe hacer una copia de esa matriz sin tocar su puntero interno, y necesita clonar todos los objetos (para que no esté modificando los originales cuando realice cambios en la copia) matriz), use esto.
El truco para no tocar el puntero interno de la matriz es asegurarse de que está trabajando con una copia de la matriz y no con la matriz original (o una referencia a ella), por lo que usar un parámetro de función hará el trabajo (por lo tanto, Esta es una función que toma una matriz).
Tenga en cuenta que aún necesitará implementar __clone () en sus objetos si desea que sus propiedades también se clonen.
Esta función funciona para cualquier tipo de matriz (incluido el tipo mixto).
function array_clone($array){return array_map(function($element){return((is_array($element))? array_clone($element):((is_object($element))? clone $element
: $element
));}, $array);}
Tenga en cuenta que este es un caso un poco especial. Además, tenga en cuenta que esto solo clonará las referencias de primer nivel. Si tiene una matriz profunda, no clonará los nodos más profundos, si son referencias. Puede que no sea un problema en tu caso, pero solo tenlo en cuenta.
troelskn
44
@troelskn Lo arreglé agregando algo de recursión. Esta función ahora funcionaría en cualquier tipo de matriz, incluidos los tipos mixtos. También funciona igual de bien para matrices simples, por lo que ya no está localizado. Básicamente es una máquina universal de clonación de matrices. Aún necesitaría definir la función __clone () en sus objetos si son profundos, pero eso está más allá del "alcance" de esta función (perdón por el mal juego de palabras).
Andrew Larsson
2
Creo firmemente que esta es la respuesta real a esta pregunta, la única forma en que he visto copiar en profundidad una matriz que contiene objetos.
Patrick
No itera las propiedades de los objetos que pueden tener otras matrices y objetos referenciados.
ya.teck
66
Este uso de __FUNCTION__es brillante.
zessx
29
Cuando tu lo hagas
$array_x = $array_y;
PHP copia la matriz, así que no estoy seguro de cómo te habrías quemado. Para su caso
global $foo;
$foo = $obj->bar;
Debería funcionar bien.
Para quemarse, creo que tendrías que haber estado usando referencias o esperando que los objetos dentro de las matrices sean clonados.
sí, pero las claves serán modificadas, cita: los valores en la matriz de entrada con claves numéricas se volverán a numerar con claves incrementales que comienzan desde cero en la matriz de resultados.
En general, funciona bien, sin embargo, en algunos casos puede arrojar una excepción porque no todas las variables son serializables (por ejemplo, cierres y conexiones de bases de datos).
ya.teck
Otra cosa a tener en cuenta es que las referencias a objetos se pueden restaurar si una clase implementa el método mágico __wakeup.
ya.teck
Gracias, finalmente algo que realmente funciona, no las otras respuestas de Bollock que tienen muchos votos positivos, seguramente no trataron con una matriz de objetos como se especifica en la pregunta donde podría cambiar el número de elementos en la matriz, pero definitivamente no las referencias a la objetos dentro de ellos
// original: {"foo":"bar","fiz":"baz","new":"val"}// cloned: {"foo":"bar","fiz":"baz"}// cloned with reassignment:{"foo":"changed","fiz":"baz"}// cloned with new values:{"foo":"bar","fiz":"baz","add":"new"}
¿Qué pasa array_slice($arr, 0)o cuando no te importan las llaves array_values($arr)? Estoy pensando que podrían ser más rápidos que buscar en una matriz. Además, en javascript, es bastante popular usarlo Array.slice()para clonar matrices.
Christian
En JS tenemos Object para pares clave-valor y Array . PHP no hace esta diferencia. Para matrices PHP con índices numerados, array_slicey todos los demás métodos mencionados aquí funcionan muy bien. Pero si desea fusionar varios pares clave-valor (como también es posible con JS-Objects vía Object.assigno la sintaxis spread ), array_replacepuede ser más útil.
Putzi San
@ Christian gracias por la sugerencia de array_values()que funcionó perfectamente para mi caso de uso.
Bigsee
11
Si solo tiene tipos básicos en su matriz, puede hacer esto:
$copy = json_decode( json_encode($array),true);
No necesitará actualizar las referencias manualmente
. Sé que no funcionará para todos, pero funcionó para mí.
+1 esto es algo realmente malo, pero es técnicamente correcto e inteligente. Si veía esto en el código, me enfrentaría a la palma, pero no puedo evitar que me guste.
Reactgular
4
Como esto no estaba cubierto en ninguna de las respuestas y ahora está disponible en PHP 5.3 (se suponía que la publicación original estaba usando 5.2).
Para mantener una estructura de matriz y cambiar sus valores, prefiero usar array_replaceo array_replace_recursivedependiendo de mi caso de uso.
Aquí hay un ejemplo usando array_replacey array_replace_recursivedemostrando que es capaz de mantener el orden indexado y capaz de eliminar una referencia.
Funciona en matrices indexadas indexadas o indexadas
$o1 =new stdClass;
$a ='d';//This is the base array or the initial structure
$o1->ar1 =['a','b',['ca','cb']];
$o1->ar1[3]=& $a;//set 3rd offset to reference $a//direct copy (not passed by reference)
$o1->ar2 = $o1->ar1;//alternatively array_replace($o1->ar1, []);
$o1->ar1[0]='z';//set offset 0 of ar1 = z do not change ar2
$o1->ar1[3]='e';//$a = e (changes value of 3rd offset to e in ar1 and ar2)//copy and remove reference to 3rd offset of ar1 and change 2nd offset to a new array
$o1->ar3 = array_replace($o1->ar1,[2=>['aa'],3=>'d']);//maintain original array of the 2nd offset in ar1 and change the value at offset 0//also remove reference of the 2nd offset//note: offset 3 and 2 are transposed
$o1->ar4 = array_replace_recursive($o1->ar1,[3=>'f',2=>['bb']]);
var_dump($o1);
<?php
// Array of available fruits
$fruits = array("lemons"=>1,"oranges"=>4,"bananas"=>5,"apples"=>10);
$fruitsArrayObject =newArrayObject($fruits);
$fruitsArrayObject['pears']=4;// create a copy of the array
$copy = $fruitsArrayObject->getArrayCopy();
print_r($copy);?>
En php array, solo debe asignarlos a otra variable para obtener una copia de esa matriz. Pero primero debe asegurarse de su tipo, ya sea array o arrayObject o stdObject.
Respuestas:
En PHP, las matrices se asignan por copia, mientras que los objetos se asignan por referencia. Esto significa que:
Rendirá:
Mientras:
Rendimientos:
Podría confundirse con complejidades como
ArrayObject
, que es un objeto que actúa exactamente como una matriz. Sin embargo, al ser un objeto, tiene semántica de referencia.Editar: @AndrewLarsson plantea un punto en los comentarios a continuación. PHP tiene una característica especial llamada "referencias". Son algo similares a los punteros en lenguajes como C / C ++, pero no son lo mismo. Si su matriz contiene referencias, mientras la matriz se pasa por copia, las referencias aún se resolverán en el objetivo original. Por supuesto, ese suele ser el comportamiento deseado, pero pensé que valía la pena mencionarlo.
fuente
$copy = $original;
. Lo que no funciona si los elementos de la matriz son referencias.php
nos presenta el resultado menos esperado , porque esta solución no siempre funciona .$a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprimearray0
mientras$a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprimearray1
. Aparentemente, algunas matrices se copian por referencia.PHP copiará la matriz por defecto. Las referencias en PHP deben ser explícitas.
fuente
Si tiene una matriz que contiene objetos, debe hacer una copia de esa matriz sin tocar su puntero interno, y necesita clonar todos los objetos (para que no esté modificando los originales cuando realice cambios en la copia) matriz), use esto.
El truco para no tocar el puntero interno de la matriz es asegurarse de que está trabajando con una copia de la matriz y no con la matriz original (o una referencia a ella), por lo que usar un parámetro de función hará el trabajo (por lo tanto, Esta es una función que toma una matriz).
Tenga en cuenta que aún necesitará implementar __clone () en sus objetos si desea que sus propiedades también se clonen.
Esta función funciona para cualquier tipo de matriz (incluido el tipo mixto).
fuente
__FUNCTION__
es brillante.Cuando tu lo hagas
PHP copia la matriz, así que no estoy seguro de cómo te habrías quemado. Para su caso
Debería funcionar bien.
Para quemarse, creo que tendrías que haber estado usando referencias o esperando que los objetos dentro de las matrices sean clonados.
fuente
array_merge()
es una función en la que puedes copiar una matriz a otra en PHP.fuente
$a_c = array_combine(array_keys($a), array_values($a))
.simple y hace una copia profunda rompiendo todos los enlaces
fuente
Me gusta
array_replace
(oarray_replace_recursive
)$cloned = array_replace([], $YOUR_ARRAY);
Funciona como
Object.assign
desde JavaScript.resultará en
fuente
array_slice($arr, 0)
o cuando no te importan las llavesarray_values($arr)
? Estoy pensando que podrían ser más rápidos que buscar en una matriz. Además, en javascript, es bastante popular usarloArray.slice()
para clonar matrices.array_slice
y todos los demás métodos mencionados aquí funcionan muy bien. Pero si desea fusionar varios pares clave-valor (como también es posible con JS-Objects víaObject.assign
o la sintaxis spread ),array_replace
puede ser más útil.array_values()
que funcionó perfectamente para mi caso de uso.Si solo tiene tipos básicos en su matriz, puede hacer esto:
No necesitará actualizar las referencias manualmente
. Sé que no funcionará para todos, pero funcionó para mí.
fuente
Como esto no estaba cubierto en ninguna de las respuestas y ahora está disponible en PHP 5.3 (se suponía que la publicación original estaba usando 5.2).
Para mantener una estructura de matriz y cambiar sus valores, prefiero usar
array_replace
oarray_replace_recursive
dependiendo de mi caso de uso.http://php.net/manual/en/function.array-replace.php
Aquí hay un ejemplo usando
array_replace
yarray_replace_recursive
demostrando que es capaz de mantener el orden indexado y capaz de eliminar una referencia.http://ideone.com/SzlBUZ
El siguiente código está escrito utilizando la sintaxis de matriz corta disponible desde PHP 5.4 que reemplaza
array()
con[]
. http://php.net/manual/en/language.types.array.phpFunciona en matrices indexadas indexadas o indexadas
Salida:
fuente
Sé esto hace mucho tiempo, pero esto funcionó para mí ...
fuente
Esta es la forma en que estoy copiando mis matrices en Php:
Esto produce:
fuente
$test2 = $test;
? ¿Qué problema estáArrayObject
resolviendo aquí?fuente
La forma más segura y barata que encontré es:
Esto también tiene el beneficio de reindexar la matriz.
Esto no funcionará como se esperaba en una matriz asociativa (hash), pero tampoco la mayoría de las respuestas anteriores.
fuente
Crea una copia del objeto Array
de https://www.php.net/manual/en/arrayobject.getarraycopy.php
fuente
Define esto:
Copie $ _ARRAY en $ _ARRAY2:
fuente
En php array, solo debe asignarlos a otra variable para obtener una copia de esa matriz. Pero primero debe asegurarse de su tipo, ya sea array o arrayObject o stdObject.
Para la matriz php simple:
fuente
fuente
$arr_one_copy = array_combine(array_keys($arr_one), $arr_one);
Solo para publicar una solución más;)
fuente
Conserva tanto la clave como los valores. La matriz 'a' es una copia exacta de la matriz 'b'
fuente