2015-01-07 2 views
61

Ich bin ein Anfänger in der Swift-Sprache.Wie erstelle ich eine exakte Kopie eines Arrays?

Wie würde ich ein exaktes Duplikat eines Arrays erstellen?

Ich habe es schwer, Informationen über das Duplizieren eines Arrays in Swift zu finden.

Ich versuchte .copy()

var originalArray = [1, 2, 3, 4] 
var duplicateArray = originalArray.copy() 
+4

Warum weisen Sie den Wert nicht direkt wie folgt zu: 'var duplicateArray = originalArray' –

+0

Vielen Dank! Es funktionierte! – Patrick

Antwort

121

Arrays haben vollen Wert Semantik in Swift verwendet wird, so gibt es keine Notwendigkeit für etwas Phantasie.

var duplicateArray = originalArray ist alles was Sie brauchen.

Wenn der Inhalt Ihres Arrays ein Referenztyp ist, dann werden ja nur die Zeiger auf Ihre Objekte kopiert. Um eine tiefe Kopie des Inhalts durchzuführen, verwenden Sie stattdessen map und führen eine Kopie jeder Instanz durch. Für Foundation Klassen, die mit dem NSCopying Protokoll entsprechen, können Sie die 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 

Hinweis, dass es Gefahren hier, dass Swift Wert Semantik arbeiten Sie davor zu schützen, zum Beispiel, da NSArray eine unveränderliche Array repräsentiert , seine copy Methode gibt nur einen Verweis auf sich selbst zurück, so dass der obige Test zu unerwarteten Ergebnissen führen würde.

+0

Ich habe versucht, dies in Spielplatz mit diesem einfachen Code 'var x = [UIView(), UIView(), UIView()] var y = x für i in x { NSLog ("% p", i) } println ("---") für i in y { NSLog ("% p", i) } 'und ich habe diese Ausgabe:' 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 --- 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 'Sieht nicht so aus, als ob es kopiert wird, weißt du warum? –

+0

@PNGamingPower: x enthält Adressen. y enthält Kopien dieser Adressen. Wenn Sie x [0] ändern, wird y [0] nicht geändert. (versuche x [0] = x [1], y [0] ändert sich nicht). So ist y eine tiefe Kopie von x. Aber Sie haben nur die Zeiger kopiert, nicht was sie zeigen. – ragnarius

+0

@ragnarius so im Grunde müssen wir definieren, was "kopieren" bedeutet, entweder den Zeiger oder den Wert zu kopieren. Daher ist dies die Lösung für das Kopieren/Duplizieren des Arrays von Zeigern, aber wie duplizieren Sie das Array von Werten? Das Ziel wäre 'x [0] == x [1]' aber 'x [0] === y [0]' sollte fehlschlagen –

20

Nate ist korrekt. Wenn Sie mit primitiven Arrays arbeiten, müssen Sie dem originalArray duplicateArray zuweisen. ist

var originalArray = [1, 2, 3, 4] as NSArray 

var duplicateArray = NSArray(array:originalArray, copyItems: true) 
+0

Das ist großartig! Vielen Dank! – Patrick

+0

Große Antwort, danke! – RainCast

10

Für normale Objekte, was getan werden kann, ein implementieren:

Aus Gründen der Vollständigkeit, wenn Sie ein NSArray Objekt gearbeitet, Sie folgendes zu tun, um eine vollständige Kopie eines NSArray tun würde, Protokoll, das Kopieren unterstützt, und die Objektklasse machen implementiert dieses Protokoll wie folgt aus:

protocol Copying { 
    init(original: Self) 
} 

extension Copying { 
    func copy() -> Self { 
     return Self.init(original: self) 
    } 
} 

und dann die Array-Erweiterung für das Klonen:

extension Array where Element: Copying { 
    func clone() -> Array { 
     var copiedArray = Array<Element>() 
     for element in self { 
      copiedArray.append(element.copy()) 
     } 
     return copiedArray 
    } 
} 

und das ist ziemlich viel es, sehen Code und eine Stichprobenkontrolle dieses gist

+0

Das hat viel Zeit gespart, Danke. – Abhijit

+0

Für Unterklassen kann das Protokoll nicht garantieren, dass die Anforderung init mit dem Typ der Unterklasse implementiert wird. Sie deklarieren ein Kopierprotokoll, das die Kopie für Sie implementiert, aber Sie implementieren immer noch clone(), das macht keinen Sinn. – Binarian

+1

@iGodric Kopie ist für Elemente in der Sammlung, und Klon ist für die gesamte Sammlung verfügbar, wenn Kopie für seine Elemente implementiert ist. Sinn ergeben? Außerdem stellt der Compiler sicher, dass Unterklassen dem Protokoll folgen, das ihre Eltern benötigen. – johnbakers

8

Es gibt eine dritte Option, Nate Antwort:

let z = x.map { $0 } // different array with same objects 

* EDITED * bearbeiten beginnt hier

Oben ist im Wesentlichen das Gleiche wie unten und die tatsächliche Verwendung des Gleichheitsoperators unten wird besser funktionieren, da das Array nicht kopiert wird, wenn es nicht geändert wird (dies ist beabsichtigt).

let z = x 

Lesen Sie mehr hier: https://developer.apple.com/swift/blog/?id=10

* EDITED * bearbeiten endet hier

Hinzufügen oder auf dieses Array zu entfernen wird nicht das ursprüngliche Array beeinflussen. Das Ändern aller Eigenschaften des Objekts, die das Array enthält, wird jedoch im ursprünglichen Array angezeigt. Da die Objekte im Array keine Kopien sind (unter der Annahme, dass das Array Objekte hält, keine primitiven Zahlen).

+0

es wirkt, ich habe es getestet. Es gibt zwei Arrays, wenn Sie sich in 1 ändern, wird die zweite bewirkt –

+0

Nein, tut es nicht, es sei denn, Array enthält primitive Typen anstelle von Objekten. Dann wirkt es wie in der Antwort angegeben. Ein einfacher Testfall: 'var array1: [String] = [" john "," alan "," kristen "]; drucken (array1); var array2 = array1.map {$ 0}; Drucken (Array2); array2 [0] = "James"; drucken (array1); print (array2); ' – oyalhi

+0

Bitte beachten Sie diese Vorlage, die ich zum besseren Beispiel mit einer benutzerdefinierten Klasse erstellt habe: https://gist.github.com/oyalhi/3b9a415cf20b5b54bb3833817db059ce – oyalhi