Gibt es eine Funktion zum Erstellen einer Kopie eines PHP-Arrays in ein anderes?
529
Gibt es eine Funktion zum Erstellen einer Kopie eines PHP-Arrays in ein anderes?
Ich wurde einige Male beim Versuch, PHP-Arrays zu kopieren, verbrannt. Ich möchte ein innerhalb eines Objekts definiertes Array in ein globales außerhalb kopieren.
Sie könnten durch Feinheiten wie verwirrt werden ArrayObject ein Objekt, das sich genau wie ein Array verhält. Als Objekt hat es jedoch eine Referenzsemantik.
Bearbeiten: @AndrewLarsson wirft einen Punkt in den Kommentaren unten auf. PHP hat eine spezielle Funktion namens "Referenzen". Sie ähneln Zeigern in Sprachen wie C / C ++, sind aber nicht ganz gleich. Wenn Ihr Array Referenzen enthält, werden die Referenzen weiterhin an das ursprüngliche Ziel aufgelöst, während das Array selbst kopiert wird. Das ist natürlich normalerweise das gewünschte Verhalten, aber ich fand es erwähnenswert.
Du hast die Frage nicht beantwortet. Sie haben nur das Problem erklärt. Was für das OP höchstwahrscheinlich das ist, wonach er gesucht hat. Für mich (und auch für andere), die fast vier Jahre später mit einem ähnlichen Problem hierher kommen, habe ich jedoch immer noch keine gute Möglichkeit, ein Array zu klonen, ohne das ursprüngliche Array zu ändern (das auch interne Zeiger enthält). Ich nehme an, es ist Zeit für mich, meine eigene Frage zu stellen.
Andrew Larsson
28
@ AndrewLarsson Aber PHP macht das standardmäßig - das ist der Kern davon. Verweise werden jedoch nicht aufgelöst. Wenn Sie dies benötigen, müssen Sie das Array rekursiv durchlaufen und ein neues erstellen. Wenn das Quellarray Objekte enthält und diese geklont werden sollen, müssen Sie dies manuell tun. Denken Sie auch daran, dass Referenzen in PHP nicht mit Zeigern in C identisch sind. Ohne etwas über Ihren Fall zu wissen, kann ich vorschlagen, dass es seltsam ist, im ersten Fall eine Reihe von Referenzen zu haben, insbesondere wenn Sie nicht beabsichtigen, diese zu behandeln sie als Referenzen? Was ist der Anwendungsfall?
Troelskn
1
@troelskn Ich habe eine Antwort auf diese Frage mit einer Lösung für mein Problem hinzugefügt
Andrew Larsson
3
Aber was ist, wenn es nicht erwünschtes Verhalten ist? Die Frage fragt, wie man eine tiefe Kopie macht. Es ist offensichtlich nicht erwünscht. Ihre Antwort ist nicht besser als : $copy = $original;. Was nicht funktioniert, wenn die Array-Elemente Referenzen sind.
Doug65536
8
Wie immer phppräsentiert uns das am wenigsten erwartete Ergebnis , da diese Lösung nicht immer funktioniert . $a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];druckt array0während $a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];druckt array1. Anscheinend werden einige Arrays als Referenz kopiert.
Tino
186
PHP kopiert das Array standardmäßig. Referenzen in PHP müssen explizit sein.
$a = array(1,2);
$b = $a;// $b will be a different array
$c =&$a;// $c will be a reference to $a
Die Verwendung der Referenz kann wichtig sein, wenn das Array sehr groß ist. Ich bin nicht sicher, aber ich gehe davon aus, dass dies zu einem geringeren Speicherverbrauch und einer besseren Leistung führen sollte (es ist nicht erforderlich, das gesamte Array in den Speicher zu kopieren).
Robsch
11
@robsch - Auf der Ebene der Programmlogik wird das Array kopiert. Im Speicher wird es jedoch erst kopiert, wenn es geändert wurde - da PHP für alle Typen die Copant-on-Write-Semantik verwendet. stackoverflow.com/questions/11074970/…
Jessica Knight
@CoreyKnight Gut zu wissen. Danke dafür.
Robsch
4
Beachten Sie, dass dies nicht für verschachtelte Arrays gilt, da es sich um Referenzen handelt und Sie mit einem kaputten Durcheinander
enden
45
Wenn Sie ein Array haben, das Objekte enthält, müssen Sie eine Kopie dieses Arrays erstellen, ohne den internen Zeiger zu berühren, und Sie müssen alle Objekte klonen (damit Sie die Originale nicht ändern, wenn Sie Änderungen am kopierten Objekt vornehmen Array), benutze dies.
Der Trick, den internen Zeiger des Arrays nicht zu berühren, besteht darin, sicherzustellen, dass Sie mit einer Kopie des Arrays arbeiten und nicht mit dem ursprünglichen Array (oder einem Verweis darauf). Wenn Sie also einen Funktionsparameter verwenden, wird die Aufgabe erledigt (also Dies ist eine Funktion, die ein Array aufnimmt.
Beachten Sie, dass Sie __clone () weiterhin für Ihre Objekte implementieren müssen, wenn deren Eigenschaften auch geklont werden sollen.
Diese Funktion funktioniert für jeden Array-Typ (einschließlich gemischter Typen).
function array_clone($array){return array_map(function($element){return((is_array($element))? array_clone($element):((is_object($element))? clone $element
: $element
));}, $array);}
Denken Sie daran, dass dies ein Sonderfall ist. Beachten Sie außerdem, dass dadurch nur die Referenzen der ersten Ebene geklont werden. Wenn Sie ein tiefes Array haben, werden die tieferen Knoten nicht geklont, wenn es sich um Referenzen handelt. Könnte in Ihrem Fall kein Problem sein, aber denken Sie daran.
Troelskn
4
@troelskn Ich habe es behoben, indem ich eine Rekursion hinzugefügt habe. Diese Funktion funktioniert jetzt für alle Arten von Arrays, einschließlich gemischter Typen. Es funktioniert auch genauso gut für einfache Arrays, sodass es nicht mehr lokalisiert ist. Es ist im Grunde eine universelle Array-Klonmaschine. Sie müssten die __clone () -Funktion in Ihren Objekten noch definieren, wenn sie tief sind, aber das würde den "Umfang" dieser Funktion sprengen (entschuldigen Sie das schlechte Wortspiel).
Andrew Larsson
2
Ich bin der festen Überzeugung, dass dies die eigentliche Antwort auf diese Frage ist. Der einzige Weg, den ich gesehen habe, um ein Array, das Objekte enthält, tatsächlich tief zu kopieren.
Patrick
Objekteigenschaften, die möglicherweise andere Arrays und referenzierte Objekte enthalten, werden nicht iteriert.
ya.teck
6
Diese Verwendung von __FUNCTION__ist brillant.
Zessx
29
Wenn Sie das tun
$array_x = $array_y;
PHP kopiert das Array, daher bin ich mir nicht sicher, wie Sie sich verbrannt hätten. Für Ihren Fall
global $foo;
$foo = $obj->bar;
sollte gut funktionieren.
Um verbrannt zu werden, müssten Sie entweder Referenzen verwendet haben oder erwarten, dass Objekte in den Arrays geklont werden.
Ja, aber die Schlüssel werden geändert. Zitat: Werte im Eingabearray mit numerischen Schlüsseln werden mit inkrementierenden Schlüsseln beginnend mit Null im Ergebnisarray neu nummeriert.
Im Allgemeinen funktioniert es einwandfrei, in einigen Fällen kann jedoch eine Ausnahme ausgelöst werden, da nicht alle Variablen serialisierbar sind (z. B. Schließungen und Datenbankverbindungen).
ya.teck
Beachten Sie außerdem, dass Objektreferenzen wiederhergestellt werden können, wenn eine Klasse die magische Methode __wakeup implementiert.
ya.teck
Danke, endlich etwas, das wirklich funktioniert, nicht die anderen Bollock-Antworten mit vielen positiven Stimmen, sie haben sich sicherlich nicht mit Arrays von Objekten befasst, wie in der Frage angegeben, wo sich die Anzahl der Elemente im Array ändern könnte, aber definitiv nicht mit den Verweisen auf das Objekte in ihnen
// 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"}
Was ist mit array_slice($arr, 0)oder wenn Sie sich nicht für Schlüssel interessieren array_values($arr)? Ich denke, sie sind möglicherweise schneller als die Suche in einem Array. In Javascript ist es auch sehr beliebt, Array.slice()Arrays zu klonen.
Christian
In JS haben wir Object für Schlüssel-Wert-Paare und Array . PHP macht diesen Unterschied nicht. Für PHP-Arrays mit nummerierten Indizes array_slicefunktionieren alle anderen hier genannten Methoden sehr gut. Wenn Sie jedoch mehrere Schlüssel-Wert-Paare zusammenführen möchten (wie dies auch bei JS-Objekten über Object.assignoder über die Spread-Syntax möglich ist ), array_replacekann dies nützlicher sein.
Putzi San
@Christian danke für den Vorschlag, der array_values()perfekt für meinen Anwendungsfall funktioniert hat.
Bigsee
11
Wenn Ihr Array nur grundlegende Typen enthält, können Sie dies tun:
$copy = json_decode( json_encode($array),true);
Sie müssen die Referenzen nicht manuell aktualisieren.
Ich weiß, dass es nicht für alle funktioniert, aber es hat für mich funktioniert
+1 das ist eine wirklich schlechte Sache, aber technisch korrekt und klug. Wenn ich das im Code sehen würde, würde ich mich der Handfläche stellen, aber ich kann nicht anders, als es zu mögen.
Reactgular
4
Da dies in keiner der Antworten behandelt wurde und jetzt in PHP 5.3 verfügbar ist (vorausgesetzt, Original Post verwendete 5.2).
Um eine Array-Struktur beizubehalten und ihre Werte zu ändern, bevorzuge ich die Verwendung array_replaceoder array_replace_recursiveabhängig von meinem Anwendungsfall.
Hier ist ein Beispiel, in dem verwendet array_replaceund array_replace_recursivedemonstriert wird, dass die indizierte Reihenfolge beibehalten und eine Referenz entfernt werden kann.
Funktioniert mit Offset-indizierten und namenindizierten Arrays
$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);?>
Im PHP-Array müssen Sie sie nur einer anderen Variablen zuweisen, um eine Kopie dieses Arrays zu erhalten. Aber zuerst müssen Sie sicherstellen, dass es sich um einen Typ handelt, ob es sich um Array oder ArrayObject oder StdObject handelt.
Antworten:
In PHP werden Arrays durch Kopieren zugewiesen, während Objekte durch Referenz zugewiesen werden. Das bedeutet, dass:
Wird ergeben:
Wohingegen:
Ausbeuten:
Sie könnten durch Feinheiten wie verwirrt werden
ArrayObject
ein Objekt, das sich genau wie ein Array verhält. Als Objekt hat es jedoch eine Referenzsemantik.Bearbeiten: @AndrewLarsson wirft einen Punkt in den Kommentaren unten auf. PHP hat eine spezielle Funktion namens "Referenzen". Sie ähneln Zeigern in Sprachen wie C / C ++, sind aber nicht ganz gleich. Wenn Ihr Array Referenzen enthält, werden die Referenzen weiterhin an das ursprüngliche Ziel aufgelöst, während das Array selbst kopiert wird. Das ist natürlich normalerweise das gewünschte Verhalten, aber ich fand es erwähnenswert.
quelle
$copy = $original;
. Was nicht funktioniert, wenn die Array-Elemente Referenzen sind.php
präsentiert uns das am wenigsten erwartete Ergebnis , da diese Lösung nicht immer funktioniert .$a=array(); $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
drucktarray0
während$a=$GLOBALS; $b=$a; $b["x"]=0; $c=$b; $b["x"]=1; echo gettype($b), $c["x"];
drucktarray1
. Anscheinend werden einige Arrays als Referenz kopiert.PHP kopiert das Array standardmäßig. Referenzen in PHP müssen explizit sein.
quelle
Wenn Sie ein Array haben, das Objekte enthält, müssen Sie eine Kopie dieses Arrays erstellen, ohne den internen Zeiger zu berühren, und Sie müssen alle Objekte klonen (damit Sie die Originale nicht ändern, wenn Sie Änderungen am kopierten Objekt vornehmen Array), benutze dies.
Der Trick, den internen Zeiger des Arrays nicht zu berühren, besteht darin, sicherzustellen, dass Sie mit einer Kopie des Arrays arbeiten und nicht mit dem ursprünglichen Array (oder einem Verweis darauf). Wenn Sie also einen Funktionsparameter verwenden, wird die Aufgabe erledigt (also Dies ist eine Funktion, die ein Array aufnimmt.
Beachten Sie, dass Sie __clone () weiterhin für Ihre Objekte implementieren müssen, wenn deren Eigenschaften auch geklont werden sollen.
Diese Funktion funktioniert für jeden Array-Typ (einschließlich gemischter Typen).
quelle
__FUNCTION__
ist brillant.Wenn Sie das tun
PHP kopiert das Array, daher bin ich mir nicht sicher, wie Sie sich verbrannt hätten. Für Ihren Fall
sollte gut funktionieren.
Um verbrannt zu werden, müssten Sie entweder Referenzen verwendet haben oder erwarten, dass Objekte in den Arrays geklont werden.
quelle
array_merge()
ist eine Funktion, mit der Sie ein Array in PHP in ein anderes kopieren können.quelle
$a_c = array_combine(array_keys($a), array_values($a))
.einfach und macht tiefe Kopie alle Links zu brechen
quelle
Ich mag
array_replace
(oderarray_replace_recursive
).$cloned = array_replace([], $YOUR_ARRAY);
Es funktioniert wie mit
Object.assign
JavaScript.wird darin enden, dass
quelle
array_slice($arr, 0)
oder wenn Sie sich nicht für Schlüssel interessierenarray_values($arr)
? Ich denke, sie sind möglicherweise schneller als die Suche in einem Array. In Javascript ist es auch sehr beliebt,Array.slice()
Arrays zu klonen.array_slice
funktionieren alle anderen hier genannten Methoden sehr gut. Wenn Sie jedoch mehrere Schlüssel-Wert-Paare zusammenführen möchten (wie dies auch bei JS-Objekten überObject.assign
oder über die Spread-Syntax möglich ist ),array_replace
kann dies nützlicher sein.array_values()
perfekt für meinen Anwendungsfall funktioniert hat.Wenn Ihr Array nur grundlegende Typen enthält, können Sie dies tun:
Sie müssen die Referenzen nicht manuell aktualisieren.
Ich weiß, dass es nicht für alle funktioniert, aber es hat für mich funktioniert
quelle
Da dies in keiner der Antworten behandelt wurde und jetzt in PHP 5.3 verfügbar ist (vorausgesetzt, Original Post verwendete 5.2).
Um eine Array-Struktur beizubehalten und ihre Werte zu ändern, bevorzuge ich die Verwendung
array_replace
oderarray_replace_recursive
abhängig von meinem Anwendungsfall.http://php.net/manual/en/function.array-replace.php
Hier ist ein Beispiel, in dem verwendet
array_replace
undarray_replace_recursive
demonstriert wird, dass die indizierte Reihenfolge beibehalten und eine Referenz entfernt werden kann.http://ideone.com/SzlBUZ
Der folgende Code geschrieben wird mit der kurzen Array - Syntax verfügbar seit PHP 5.4 die an der Stelle
array()
mit[]
. http://php.net/manual/en/language.types.array.phpFunktioniert mit Offset-indizierten und namenindizierten Arrays
Ausgabe:
quelle
Ich weiß das schon vor langer Zeit, aber das hat bei mir funktioniert.
quelle
So kopiere ich meine Arrays in Php:
Dies gibt aus:
quelle
$test2 = $test;
? Welches ProblemArrayObject
löst sich hier?quelle
Der sicherste und billigste Weg, den ich gefunden habe, ist:
Dies hat auch den Vorteil, dass das Array neu indiziert wird.
Dies funktioniert nicht wie erwartet für assoziatives Array (Hash), aber auch nicht für die meisten vorherigen Antworten.
quelle
Erstellt eine Kopie des ArrayObject
von https://www.php.net/manual/en/arrayobject.getarraycopy.php
quelle
Definieren Sie dies:
Kopieren Sie $ _ARRAY nach $ _ARRAY2:
quelle
Im PHP-Array müssen Sie sie nur einer anderen Variablen zuweisen, um eine Kopie dieses Arrays zu erhalten. Aber zuerst müssen Sie sicherstellen, dass es sich um einen Typ handelt, ob es sich um Array oder ArrayObject oder StdObject handelt.
Für einfaches PHP-Array:
quelle
quelle
$arr_one_copy = array_combine(array_keys($arr_one), $arr_one);
Nur um noch eine Lösung zu posten;)
quelle
Erhält sowohl Schlüssel als auch Werte. Array 'a' ist eine exakte Kopie von Array 'b'
quelle