Warum weisen Sie den Wert nicht direkt so zu:var duplicateArray = originalArray
Dharmesh Kheni
1
Das funktioniert in meinem Fall nicht. Dadurch wird ein weiteres Objekt erstellt, das nur auf dasselbe Array verweist, und Sie erhalten zwei Variablen, die auf dasselbe Array verweisen.
user1060500
Antworten:
176
Arrays haben in Swift eine vollständige Semantik, sodass nichts Besonderes erforderlich ist.
var duplicateArray = originalArray ist alles, was du brauchst.
Wenn der Inhalt Ihres Arrays ein Referenztyp ist, werden die Zeiger nur auf Ihre Objekte kopiert. Um eine tiefe Kopie des Inhalts zu erstellen, würden Sie stattdessen verwendenmap eine Kopie jeder Instanz und ausführen. Für Foundation-Klassen, die dem NSCopyingProtokoll entsprechen, können Sie die folgende copy()Methode verwenden:
let x =[NSMutableArray(),NSMutableArray(),NSMutableArray()]let y = x
let z = x.map { $0.copy()}
x[0]=== y[0]// true
x[0]=== z[0]//false
Beachten Sie, dass es hier Fallstricke gibt, vor denen die Wertsemantik von Swift Sie schützt. Da NSArraysie beispielsweise ein unveränderliches Array darstellt, gibt ihre copyMethode nur einen Verweis auf sich selbst zurück, sodass der obige Test zu unerwarteten Ergebnissen führen würde.
Ich habe dies auf dem Spielplatz mit diesem einfachen Code versucht var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }und habe folgende Ausgabe erhalten: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 Sieht nicht so aus, als würde es kopiert, wissen Sie warum?
Phil Niedertscheider
@PNGamingPower: x enthält Adressen. y enthält Kopien dieser Adressen. Wenn Sie x [0] ändern, ändert sich y [0] nicht. (versuchen Sie x [0] = x [1], y [0] ändert sich nicht). Somit ist y eine tiefe Kopie von x. Sie haben jedoch nur die Zeiger kopiert, nicht das, worauf sie zeigen.
Ragnarius
@ragnarius, also müssen wir im Grunde definieren, was "Kopieren" bedeutet, entweder den Zeiger oder den Wert kopieren. Daher ist dies die Lösung zum Kopieren / Duplizieren des Array von Zeigern. Wie duplizieren Sie das Array von Werten? Das Ziel wäre x[0] == x[1]aber x[0] === y[0]sollte scheitern
Phil Niedertscheider
Dies sollte die akzeptierte Antwort sein, da die Wertesemantik des Arrays eine "Kopie" des Arrays unnötig macht.
Scott Ahten
Das funktioniert bei mir nicht. Wenn ich dieser Methode folge, erhalte ich zwei Referenzen, die auf dasselbe Array von Objekten verweisen. Wenn ich ein Element aus der Liste entferne, wird es in beiden Objektreferenzen wiedergegeben, da die Liste nicht kopiert wurde, sondern nur auf das Objekt verwiesen wurde.
user1060500
28
Nate ist richtig. Wenn Sie mit primitiven Arrays arbeiten, müssen Sie dem OriginalArray lediglich duplicateArray zuweisen.
Der Vollständigkeit halber würden Sie, wenn Sie ein NSArray-Objekt bearbeiten, die folgenden Schritte ausführen, um eine vollständige Kopie eines NSArray zu erstellen:
var originalArray =[1,2,3,4]asNSArrayvar duplicateArray =NSArray(array:originalArray, copyItems:true)
let z = x.map { $0}// different array with same objects
* BEARBEITET * Bearbeitung beginnt hier
Oben ist im Wesentlichen dasselbe wie unten, und die Verwendung des unten stehenden Gleichheitsoperators führt zu einer besseren Leistung, da das Array nur kopiert wird, wenn es geändert wird (dies ist beabsichtigt).
Das Hinzufügen oder Entfernen zu diesem Array wirkt sich nicht auf das ursprüngliche Array aus. Das Ändern der Eigenschaften eines Objekts, die das Array enthält, wird jedoch im ursprünglichen Array angezeigt. Da die Objekte im Array keine Kopien sind (vorausgesetzt, das Array enthält Objekte, keine primitiven Zahlen).
es wirkt, ich habe es getestet. Es gibt zwei Arrays, wenn Sie in 1 ändern, wird das zweite bewirkt
Filthy Knight
1
Nein, es sei denn, das Array enthält primitive Typen anstelle von Objekten. Dann wirkt es sich wie in der Antwort angegeben aus. Ein einfacher Testfall:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
Wenn Ihre Klasse unterstützt NSCopying, dann duplizieren Sie ein Array:let z = x.map { $0.copy as! ClassX }
John Pang
Wenn Sie Swifts BufferPointers verwenden, ist dies die Version, die Sie als direkte Kopie verwenden sollten. Bevor Sie einen Wert im Original oder im kopierten Array ändern, kopiert Swift die Werte des Originals in die Kopie und fährt dann fort. Wenn Sie stattdessen Zeiger verwenden, wird Swift dies jetzt nicht tun, wenn oder wenn Änderungen vorgenommen werden. Daher können Sie möglicherweise beide Arrays ändern.
Justin Ganzer
16
Für normale Objekte kann ein Protokoll implementiert werden, das das Kopieren unterstützt, und die Objektklasse implementiert dieses Protokoll wie folgt:
Für Unterklassen kann das Protokoll nicht garantieren, dass die Anforderung init mit dem Typ der Unterklasse implementiert ist. Sie deklarieren ein Kopierprotokoll, das das Kopieren für Sie implementiert, aber Sie implementieren immer noch clone (), was keinen Sinn ergibt.
Binarian
1
@ iGodric copy ist für Elemente in der Sammlung und clone ist für die gesamte Sammlung verfügbar. Dies ist verfügbar, wenn copy für seine Elemente implementiert ist. Sinn ergeben? Außerdem stellt der Compiler sicher, dass die Unterklassen dem Protokoll folgen, das ihre Eltern benötigen.
Johnbakers
@ Johnbakers Oh ja, jetzt sehe ich es. Danke für die Erklärung.
Binarian
Sehr saubere Implementierung und vermeidet die unnötige Hektik der Übergabe von Parametern in der object'sInit-Funktion
Sylvan D Ash
0
Wenn Sie die Elemente eines Arrays eines Klassenobjekts kopieren möchten. Dann können Sie dem folgenden Code folgen, ohne das NSCopying-Protokoll zu verwenden. Sie benötigen jedoch eine Init-Methode, die alle für Ihr Objekt erforderlichen Parameter übernimmt. Hier ist der Code für ein Beispiel zum Testen auf einem Spielplatz.
class ABC {var a =0func myCopy()-> ABC {return ABC(value:self.a)}init(value:Int){self.a = value
}}var arrayA:[ABC]=[ABC(value:1)]var arrayB:[ABC]= arrayA.map { $0.myCopy()}
arrayB.first?.a =2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints2
var duplicateArray = originalArray
Antworten:
Arrays haben in Swift eine vollständige Semantik, sodass nichts Besonderes erforderlich ist.
var duplicateArray = originalArray
ist alles, was du brauchst.Wenn der Inhalt Ihres Arrays ein Referenztyp ist, werden die Zeiger nur auf Ihre Objekte kopiert. Um eine tiefe Kopie des Inhalts zu erstellen, würden Sie stattdessen verwenden
map
eine Kopie jeder Instanz und ausführen. Für Foundation-Klassen, die demNSCopying
Protokoll entsprechen, können Sie die folgendecopy()
Methode verwenden:Beachten Sie, dass es hier Fallstricke gibt, vor denen die Wertsemantik von Swift Sie schützt. Da
NSArray
sie beispielsweise ein unveränderliches Array darstellt, gibt ihrecopy
Methode nur einen Verweis auf sich selbst zurück, sodass der obige Test zu unerwarteten Ergebnissen führen würde.quelle
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
und habe folgende Ausgabe erhalten:0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
Sieht nicht so aus, als würde es kopiert, wissen Sie warum?x[0] == x[1]
aberx[0] === y[0]
sollte scheiternNate ist richtig. Wenn Sie mit primitiven Arrays arbeiten, müssen Sie dem OriginalArray lediglich duplicateArray zuweisen.
Der Vollständigkeit halber würden Sie, wenn Sie ein NSArray-Objekt bearbeiten, die folgenden Schritte ausführen, um eine vollständige Kopie eines NSArray zu erstellen:
quelle
Es gibt eine dritte Option für Nates Antwort:
* BEARBEITET * Bearbeitung beginnt hier
Oben ist im Wesentlichen dasselbe wie unten, und die Verwendung des unten stehenden Gleichheitsoperators führt zu einer besseren Leistung, da das Array nur kopiert wird, wenn es geändert wird (dies ist beabsichtigt).
Lesen Sie hier mehr: https://developer.apple.com/swift/blog/?id=10
* BEARBEITET * Bearbeitung endet hier
Das Hinzufügen oder Entfernen zu diesem Array wirkt sich nicht auf das ursprüngliche Array aus. Das Ändern der Eigenschaften eines Objekts, die das Array enthält, wird jedoch im ursprünglichen Array angezeigt. Da die Objekte im Array keine Kopien sind (vorausgesetzt, das Array enthält Objekte, keine primitiven Zahlen).
quelle
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, dann duplizieren Sie ein Array:let z = x.map { $0.copy as! ClassX }
Für normale Objekte kann ein Protokoll implementiert werden, das das Kopieren unterstützt, und die Objektklasse implementiert dieses Protokoll wie folgt:
Und dann die Array-Erweiterung zum Klonen:
und das ist so ziemlich alles , um Code und ein Beispiel anzusehen, überprüfen Sie dieses Wesentliche
quelle
object's
Init-FunktionWenn Sie die Elemente eines Arrays eines Klassenobjekts kopieren möchten. Dann können Sie dem folgenden Code folgen, ohne das NSCopying-Protokoll zu verwenden. Sie benötigen jedoch eine Init-Methode, die alle für Ihr Objekt erforderlichen Parameter übernimmt. Hier ist der Code für ein Beispiel zum Testen auf einem Spielplatz.
quelle