2015-01-07 6 views
61

私はSwift言語の初心者です。アレイの正確な複製コピーを作成するにはどうすればよいですか?

アレイの正確な複製を作成するにはどうすればよいですか?

Swiftでアレイの複製に関する情報を見つけるのが苦労しています。

私は配列はスウィフトで完全な値の意味を持っているので、空想何のための必要はありません.copy()

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

なぜあなたはこのように直接値を割り当てません: 'var duplicateArray = originalArray' –

+0

ありがとう!出来た! – Patrick

答えて

121

を使用してみました。

var duplicateArray = originalArrayすべてが必要です。


配列の内容が参照型である場合は、これはオブジェクトへのポインタのみをコピーします。コンテンツの詳細コピーを実行するには、代わりにmapを使用し、各インスタンスのコピーを実行します。 NSCopyingプロトコルに準拠財団クラスの場合、あなたはcopy()メソッドを使用することができます。

let x = [NSMutableArray(), NSMutableArray(), NSMutableArray()] 
let y = x 
let z = x.map { $0.copy() } 

x[0] === y[0] // true 
x[0] === z[0] // false 

落とし穴がここにあります。なお、たとえばから-、NSArrayは不変の配列を表しているのでスウィフトの値のセマンティクスは、あなたを守るために働いていることそのcopyメソッドは、自身への参照を返すだけなので、上記のテストでは予期しない結果が得られます。

+0

私はこの単純なコードで遊び場でこれを試みた 'VAR X = [UIViewの()、UIViewの()、UIViewの()] VAR yをX { のNSLogでiに対する= X ( "%のP"、i)は } Y { のNSLog( "%のP"、I) } 'のIためのprintln( "---") 、私はこの出力を得た:' 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 を--- 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 'それはコピーされているように見えません、あなたはその理由を知っていますか? –

+0

@PNGamingPower:xにはアドレスが含まれています。 yにはそれらのアドレスのコピーが含まれています。 x [0]を変更すると、y [0]は変更されません。 (try x [0] = x [1]、y [0]は変更されません)。したがって、yはxの深いコピーです。しかし、指しているものではなく、ポインタだけをコピーしています。 – ragnarius

+0

@ragnariusだから、基本的に私たちはポインタや値をコピーする "コピー"の意味を定義しなければなりません。したがって、これはポインタの配列をコピー/複製するためのソリューションですが、どのように値の配列を複製しますか?目標は 'x [0] == x [1]'ですが、 'x [0] === y [0]'は失敗します。 –

20

Nateは正しいです。プリミティブ配列で作業している場合は、duplicateArrayをoriginalArrayに割り当てます。完全を期すために、あなたがNSArrayのオブジェクトを働いていた場合、あなたはNSArrayのの完全なコピーを行うには、以下のだろう

を:何ができるのか、通常のオブジェクトの場合

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

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

これは素晴らしいことです!ありがとうございました! – Patrick

+0

偉大な答え、ありがとう! – RainCast

10

を実装することですコピーをサポートし、オブジェクトクラスは、このように、このプロトコルを実装しますプロトコル:

protocol Copying { 
    init(original: Self) 
} 

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

そしてクローニングのためのアレイの拡張:

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

とネイトの答えに第三の選択肢があることは、コードを表示するために、かなりそれであり、サンプルは、このgist

+0

これは時間が節約されました、ありがとうございます。 – Abhijit

+0

サブクラスの場合、プロトコルは要求initがサブクラスの型で実装されることを保証できません。コピーを実装するコピープロトコルを宣言していますが、それでも意味をなさないclone()を実装しています。 – Binarian

+1

@iGodricコピーはコレクション内の要素用であり、複製はコレクション全体用であり、その要素にコピーが実装されている場合に使用できます。理にかなっている?また、コンパイラは、サブクラスが親が要求するプロトコルに従うようにします。 – johnbakers

8

を確認してください。

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

は* *編集がここ

を開始EDITED

上記は本質的に以下の通りであり、実際に以下の等価演算子を使用すると、配列が変更されない限り(これは設計による)コピーされないため、パフォーマンスが向上します。

let z = x 

もっとここで読む:https://developer.apple.com/swift/blog/?id=10

* *編集は元の配列には影響しません。この配列に追加または削除ここ

を終了編集しました。しかし、配列が保持しているオブジェクトのいずれかのプロパティを変更すると、元の配列に表示されます。配列内のオブジェクトはコピーではないため(プリミティブ番号ではなく配列保持オブジェクトと仮定します)。

+0

それは効果がある、私はそれをテストしました。 2つの配列があり、1が変化した場合は2番目が有効になります –

+0

配列はオブジェクトではなくプリミティブ型を保持していない限り、そうではありません。それは答えに述べられているように影響します。簡単なテストケース: 'var array1:[String] = [" john "、" alan "、" kristen "]; print(array1); var array2 = array1.map {$ 0}; print(array2); array2 [0] = "james"; print(array1); print(array2); ' – oyalhi

+0

カスタムクラスを使用したより良い例を作成したこの要点をご覧ください:https://gist.github.com/oyalhi/3b9a415cf20b5b54bb3833817db059ce – oyalhi