Você pode ficar confuso com complexidades como ArrayObject, que é um objeto que age exatamente como uma matriz. Sendo um objeto, no entanto, possui semântica de referência.
Edit: @AndrewLarsson levanta um ponto nos comentários abaixo. O PHP possui um recurso especial chamado "referências". Eles são um pouco semelhantes aos ponteiros em linguagens como C / C ++, mas não são exatamente iguais. Se sua matriz contiver referências, enquanto a própria matriz for passada por cópia, as referências ainda serão resolvidas para o destino original. É claro que esse é geralmente o comportamento desejado, mas achei que valia a pena mencionar.
Você não respondeu à pergunta. Você só explicou o problema. O qual, para o OP, é provavelmente o que ele estava procurando. No entanto, para mim (e para outros também), chegando aqui quase quatro anos depois com um problema semelhante, ainda não tenho uma boa maneira de clonar uma matriz sem modificar a matriz original (que também inclui indicadores internos). Suponho que é hora de fazer minha própria pergunta.
Andrew Larsson
28
@AndrewLarsson Mas o PHP faz isso por padrão - Essa é a essência. Porém, as referências não são resolvidas; portanto, se você precisar disso, terá que percorrer recursivamente a matriz e criar uma nova. Lembre-se também de que as referências no PHP não são as mesmas que as indicadas no C. Sem saber nada sobre o seu caso, posso sugerir que é estranho ter uma matriz de referências no primeiro caso, especialmente se você não pretende tratar eles como referências? Qual é o caso de uso?
Mas e quando não é o comportamento desejado? A pergunta pergunta como fazer uma cópia profunda . Obviamente não é desejado. A sua resposta não é melhor do que é: $copy = $original;. O que não funciona se os elementos da matriz são referências.
Doug65536
8
Como sempre, phpapresenta o resultado menos esperado , porque essa solução nem sempre funciona . $a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];imprime array0enquanto $a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];imprime array1. Aparentemente, algumas matrizes são copiadas por referência.
Tino
186
O PHP copiará a matriz por padrão. Referências em PHP devem 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 a referência pode ser importante se a matriz for enorme. Não tenho certeza, mas presumo que deva levar a menos consumo de memória e melhor desempenho (não é necessário copiar toda a matriz na memória).
robsch
11
@robsch - no nível da lógica do programa, o array é copiado. Mas na memória, ele não será copiado até que seja modificado - porque o PHP usa semântica de cópia na gravação para todos os tipos. stackoverflow.com/questions/11074970/...
Jessica Cavaleiro
@CoreyKnight É bom saber. Obrigado por isso.
robsch
4
Note que isso não é verdade para matrizes aninhadas, são referências e assim você acaba com uma bagunça quebrado
MightyPork
45
Se você possui uma matriz que contém objetos, precisa fazer uma cópia dessa matriz sem tocar no ponteiro interno e precisa que todos os objetos sejam clonados (para não modificar os originais ao fazer alterações nas cópias copiadas). array), use isso.
O truque para não tocar no ponteiro interno da matriz é garantir que você esteja trabalhando com uma cópia da matriz, e não com a matriz original (ou uma referência a ela), portanto, o uso de um parâmetro de função fará o trabalho (portanto, esta é uma função que recebe uma matriz).
Observe que você ainda precisará implementar __clone () em seus objetos se desejar que suas propriedades também sejam clonadas.
Esta função funciona para qualquer tipo de matriz (incluindo tipo misto).
function array_clone($array){return array_map(function($element){return((is_array($element))? array_clone($element):((is_object($element))? clone $element
: $element
));}, $array);}
Lembre-se de que este é um caso especial. Além disso, observe que isso clonará apenas as referências de primeiro nível. Se você possui uma matriz profunda, não clonará os nós mais profundos, se forem referências. Pode não ser um problema no seu caso, mas lembre-se disso.
troelskn
4
@troelskn Corrigi-o adicionando alguma recursão. Esta função agora funcionaria em qualquer tipo de matriz, incluindo tipos mistos. Também funciona da mesma forma para matrizes simples, portanto não está mais localizado. É basicamente uma máquina de clonagem de matriz universal. Você ainda precisa definir a função __clone () em seus objetos, se eles forem profundos, mas isso está além do "escopo" dessa função (desculpe o trocadilho).
Andrew Larsson
2
Acredito firmemente que essa é a resposta real a essa pergunta: a única maneira que vi de copiar profundamente uma matriz que contém objetos.
Patrick
Não itera as propriedades do objeto que podem ter outras matrizes e objetos referenciados.
usar o seguinte comando
6
Este uso de __FUNCTION__é brilhante.
Zessx 22/03/19
29
Quando você faz
$array_x = $array_y;
O PHP copia a matriz, então não tenho certeza de como você se queimaria. Para o seu caso,
global $foo;
$foo = $obj->bar;
deve funcionar bem.
Para se queimar, acho que você teria que usar referências ou esperar que objetos dentro das matrizes fossem clonados.
sim, mas as chaves serão modificadas, citação: Os valores na matriz de entrada com teclas numéricas serão renumerados com chaves incrementais a partir de zero na matriz de resultados.
Geralmente funciona bem, porém, em alguns casos, pode gerar uma exceção, porque nem todas as variáveis são serializáveis (por exemplo, fechamentos e conexões com o banco de dados).
usar o seguinte comando
Outro ponto a ser observado é que as referências a objetos podem ser restauradas se uma classe implementar o método mágico __wakeup.
usar o seguinte comando
Obrigado, finalmente, algo que realmente funciona, não sendo que as outras respostas vazias tenham muitas votações, elas certamente não lidaram com a matriz de objetos, como é especificado na pergunta em que o número de elementos na matriz pode mudar, mas definitivamente não são as referências ao objetos dentro deles
// 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"}
E array_slice($arr, 0)quando você não se importa com chaves array_values($arr)? Eu estou pensando que eles podem ser mais rápidos do que pesquisar em uma matriz. Além disso, em javascript, é bastante popular usar Array.slice()para clonar matrizes.
Christian
Em JS, temos Objeto para pares de valores-chave e Matriz . PHP não faz essa diferença. Para matrizes PHP com índices numerados, array_slicee todos os outros métodos mencionados aqui funcionam muito bem. Mas se você deseja mesclar vários pares de valores-chave (como também é possível com JS-Objects via Object.assignou a sintaxe de propagação ), array_replacepode ser mais útil.
Putzi San
@ Christian obrigado pela sugestão de array_values()que funcionou perfeitamente para o meu caso de uso.
bigsee 31/01/19
11
Se você tiver apenas tipos básicos em sua matriz, poderá fazer o seguinte:
$copy = json_decode( json_encode($array),true);
Você não precisará atualizar as referências manualmente
. Sei que não funcionará para todos, mas funcionou para mim
Marcar com +1 é uma coisa muito ruim de se fazer, mas é tecnicamente correto e inteligente. Se eu visse isso no código, enfrentaria a palma da mão, mas não posso deixar de gostar.
Reactgular
4
Como isso não foi abordado em nenhuma das respostas e agora está disponível no PHP 5.3 (assumindo que o Post Original estava usando o 5.2).
Para manter uma estrutura de matriz e alterar seus valores, prefiro usar array_replaceouarray_replace_recursive dependendo do meu caso de uso.
Aqui está um exemplo usando array_replaceearray_replace_recursive demonstrando que é capaz de manter a ordem indexada e capaz de remover uma referência.
Funciona em matrizes indexadas offset e indexadas por nome
$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);?>
No array php, você precisa apenas atribuí-los a outra variável para obter uma cópia desse array. Mas primeiro você precisa ter certeza do seu tipo, seja array ou arrayObject ou stdObject.
Respostas:
No PHP, matrizes são atribuídas por cópia, enquanto objetos são atribuídos por referência. Isso significa que:
Produzirá:
Enquanto que:
Rendimentos:
Você pode ficar confuso com complexidades como
ArrayObject
, que é um objeto que age exatamente como uma matriz. Sendo um objeto, no entanto, possui semântica de referência.Edit: @AndrewLarsson levanta um ponto nos comentários abaixo. O PHP possui um recurso especial chamado "referências". Eles são um pouco semelhantes aos ponteiros em linguagens como C / C ++, mas não são exatamente iguais. Se sua matriz contiver referências, enquanto a própria matriz for passada por cópia, as referências ainda serão resolvidas para o destino original. É claro que esse é geralmente o comportamento desejado, mas achei que valia a pena mencionar.
fonte
$copy = $original;
. O que não funciona se os elementos da matriz são referências.php
apresenta o resultado menos esperado , porque essa solução nem sempre funciona .$a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprimearray0
enquanto$a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
imprimearray1
. Aparentemente, algumas matrizes são copiadas por referência.O PHP copiará a matriz por padrão. Referências em PHP devem ser explícitas.
fonte
Se você possui uma matriz que contém objetos, precisa fazer uma cópia dessa matriz sem tocar no ponteiro interno e precisa que todos os objetos sejam clonados (para não modificar os originais ao fazer alterações nas cópias copiadas). array), use isso.
O truque para não tocar no ponteiro interno da matriz é garantir que você esteja trabalhando com uma cópia da matriz, e não com a matriz original (ou uma referência a ela), portanto, o uso de um parâmetro de função fará o trabalho (portanto, esta é uma função que recebe uma matriz).
Observe que você ainda precisará implementar __clone () em seus objetos se desejar que suas propriedades também sejam clonadas.
Esta função funciona para qualquer tipo de matriz (incluindo tipo misto).
fonte
__FUNCTION__
é brilhante.Quando você faz
O PHP copia a matriz, então não tenho certeza de como você se queimaria. Para o seu caso,
deve funcionar bem.
Para se queimar, acho que você teria que usar referências ou esperar que objetos dentro das matrizes fossem clonados.
fonte
array_merge()
é uma função na qual você pode copiar uma matriz para outra no PHP.fonte
$a_c = array_combine(array_keys($a), array_values($a))
.simples e faz cópias profundas quebrando todos os links
fonte
Eu gosto
array_replace
(ouarray_replace_recursive
).$cloned = array_replace([], $YOUR_ARRAY);
Funciona como
Object.assign
no JavaScript.vai resultar em
fonte
array_slice($arr, 0)
quando você não se importa com chavesarray_values($arr)
? Eu estou pensando que eles podem ser mais rápidos do que pesquisar em uma matriz. Além disso, em javascript, é bastante popular usarArray.slice()
para clonar matrizes.array_slice
e todos os outros métodos mencionados aqui funcionam muito bem. Mas se você deseja mesclar vários pares de valores-chave (como também é possível com JS-Objects viaObject.assign
ou a sintaxe de propagação ),array_replace
pode ser mais útil.array_values()
que funcionou perfeitamente para o meu caso de uso.Se você tiver apenas tipos básicos em sua matriz, poderá fazer o seguinte:
Você não precisará atualizar as referências manualmente
. Sei que não funcionará para todos, mas funcionou para mim
fonte
Como isso não foi abordado em nenhuma das respostas e agora está disponível no PHP 5.3 (assumindo que o Post Original estava usando o 5.2).
Para manter uma estrutura de matriz e alterar seus valores, prefiro usar
array_replace
ouarray_replace_recursive
dependendo do meu caso de uso.http://php.net/manual/en/function.array-replace.php
Aqui está um exemplo usando
array_replace
earray_replace_recursive
demonstrando que é capaz de manter a ordem indexada e capaz de remover uma referência.http://ideone.com/SzlBUZ
O código abaixo é escrito usando a sintaxe de matriz curta disponível desde o PHP 5.4 que substitui
array()
por[]
. http://php.net/manual/en/language.types.array.phpFunciona em matrizes indexadas offset e indexadas por nome
Resultado:
fonte
Eu sei disso há muito tempo, mas isso funcionou para mim ..
fonte
É assim que estou copiando minhas matrizes no Php:
Isso gera:
fonte
$test2 = $test;
? Que problema estáArrayObject
resolvendo aqui?fonte
A maneira mais segura e barata que encontrei é:
Isso também tem o benefício de reindexar a matriz.
Isso não funcionará como esperado no array associativo (hash), mas nem na maioria das respostas anteriores.
fonte
Cria uma cópia do ArrayObject
from https://www.php.net/manual/en/arrayobject.getarraycopy.php
fonte
Defina isso:
Copie $ _ARRAY para $ _ARRAY2:
fonte
No array php, você precisa apenas atribuí-los a outra variável para obter uma cópia desse array. Mas primeiro você precisa ter certeza do seu tipo, seja array ou arrayObject ou stdObject.
Para array php simples:
fonte
fonte
$arr_one_copy = array_combine(array_keys($arr_one), $arr_one);
Apenas para postar mais uma solução;)
fonte
Preserva a chave e os valores. A matriz 'a' é uma cópia exata da matriz 'b'
fonte