2015-01-07 39 views
61

Tôi là người mới bắt đầu bằng ngôn ngữ Swift.Làm cách nào để tạo bản sao chính xác của một mảng?

Làm thế nào tôi có thể làm cho một bản sao chính xác của một mảng?

Tôi gặp khó khăn trong việc tìm kiếm thông tin về việc sao chép một mảng trong Swift.

tôi đã cố gắng sử dụng .copy()

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

tại sao bạn không chỉ định giá trị trực tiếp như sau: 'var duplicateArray = originalArray' –

+0

Cảm ơn! Nó đã làm việc! – Patrick

Trả lời

121

Mảng có ngữ nghĩa giá trị đầy đủ trong Swift, do đó không cần bất cứ điều gì lạ mắt.

var duplicateArray = originalArray là tất cả những gì bạn cần.


Nếu nội dung của mảng của bạn là loại tham chiếu, thì có, điều này sẽ chỉ sao chép con trỏ đến đối tượng của bạn. Để thực hiện một bản sao sâu của nội dung, thay vào đó bạn sẽ sử dụng map và thực hiện một bản sao của từng trường hợp. Đối với các lớp học Foundation mà phù hợp với các giao thức NSCopying, bạn có thể sử dụng copy() phương pháp:

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

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

Lưu ý rằng có những cạm bẫy ở đây là ngữ nghĩa giá trị của Swift đang làm việc để bảo vệ bạn khỏi-ví dụ, vì NSArray đại diện cho một mảng bất biến , phương thức copy của nó chỉ trả về tham chiếu cho chính nó, do đó, kiểm tra ở trên sẽ mang lại kết quả không mong muốn.

+0

Tôi cố gắng này ở sân chơi với mã đơn giản này 'var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog ("% p", i) } println ("---") for i in y { NSLog ("% p", i) } 'và tôi đã nhận ra này:' 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 --- 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 'Không giống như nó đang được sao chép, bạn có biết tại sao không? –

+0

@PNGamingPower: x chứa địa chỉ. y chứa các bản sao của các địa chỉ đó. Nếu bạn thay đổi x [0], y [0] sẽ không thay đổi. (thử x [0] = x [1], y [0] sẽ không thay đổi). Vì vậy, y là một bản sao sâu của x.But bạn chỉ sao chép các con trỏ, không phải là những gì họ đang trỏ đến. – ragnarius

+0

@ragnarius về cơ bản chúng tôi phải xác định "bản sao" có nghĩa là sao chép con trỏ hoặc giá trị. Vì vậy đây là giải pháp sao chép/nhân đôi mảng con trỏ, nhưng làm thế nào để bạn sao chép mảng giá trị? Mục tiêu sẽ là 'x [0] == x [1]' nhưng 'x [0] === y [0]' sẽ thất bại –

20

Nate là đúng. Nếu bạn đang làm việc với các mảng nguyên thủy, tất cả những gì bạn cần làm là gán duplicateArray cho tệp originalArray.

Vì lợi ích của sự hoàn chỉnh, nếu bạn đang làm việc một đối tượng NSArray, bạn sẽ làm như sau để làm một bản sao đầy đủ của một NSArray:

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

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

Điều này thật tuyệt! Cảm ơn bạn! – Patrick

+0

Câu trả lời hay, cảm ơn! – RainCast

10

Đối với đối tượng bình thường những gì có thể được thực hiện là để thực hiện một giao thức hỗ trợ sao chép, và làm cho lớp đối tượng thực hiện giao thức này như sau:

protocol Copying { 
    init(original: Self) 
} 

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

và sau đó mở rộng mảng cho nhân bản:

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

và đó là khá nhiều nó, để xem mã số và một tấm séc mẫu này gist

+0

Điều này tiết kiệm rất nhiều thời gian, Cảm ơn bạn. – Abhijit

+0

Đối với các lớp con, giao thức không thể đảm bảo rằng init yêu cầu được thực hiện với kiểu của lớp con. Bạn đang khai báo một giao thức sao chép thực hiện sao chép cho bạn, nhưng bạn vẫn đang thực hiện sao chép(), điều đó không có ý nghĩa. – Binarian

+1

@iGhi bản sao cho các phần tử trong bộ sưu tập và bản sao là dành cho toàn bộ bộ sưu tập, có sẵn khi bản sao được triển khai cho các phần tử của nó. Có lý? Ngoài ra, trình biên dịch đảm bảo rằng các lớp con thực hiện theo giao thức mà cha mẹ chúng yêu cầu. – johnbakers

8

Có một lựa chọn thứ ba cho câu trả lời của Nate:

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

* EDITED * chỉnh sửa bắt đầu ở đây

Trên cơ bản giống như dưới đây và thực sự sử dụng toán tử bình đẳng bên dưới sẽ hoạt động tốt hơn vì mảng sẽ không được sao chép trừ khi nó bị thay đổi (theo thiết kế).

let z = x 

đọc thêm ở đây: https://developer.apple.com/swift/blog/?id=10

* EDITED * chỉnh sửa kết thúc tại đây

thêm hoặc loại bỏ để mảng này sẽ không ảnh hưởng đến các mảng ban đầu. Tuy nhiên, việc thay đổi bất kỳ thuộc tính nào của đối tượng mà mảng giữ lại sẽ được nhìn thấy trong mảng ban đầu. Bởi vì các đối tượng trong mảng không phải là bản sao (giả sử mảng giữ đối tượng, không phải là số nguyên thủy).

+0

nó có hiệu lực, tôi đã thử nghiệm nó. có hai mảng, nếu u thay đổi trong 1, thứ hai được thực hiện –

+0

Không, trừ khi mảng giữ các kiểu nguyên thủy thay vì các đối tượng. Sau đó, nó ảnh hưởng đến như đã nêu trong câu trả lời. Một trường hợp thử nghiệm đơn giản: 'var array1: [String] = [" john "," alan "," kristen "]; in (mảng1); var array2 = array1.map {$ 0}; in (mảng2); mảng2 [0] = "james"; in (mảng1); print (array2); ' – oyalhi

+0

Vui lòng xem ý chính này tôi đã tạo cho ví dụ tốt hơn bằng cách sử dụng một lớp tùy chỉnh: https://gist.github.com/oyalhi/3b9a415cf20b5b54bb3833817db059ce – oyalhi

Các vấn đề liên quan