Làm cách nào để ghép hoặc ghép các mảng trong Swift?


Câu trả lời:


691

Bạn có thể nối các mảng với +, xây dựng một mảng mới

let c = a + b
print(c) // [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]

hoặc nối một mảng với mảng khác bằng +=(hoặc append):

a += b

// Or:
a.append(contentsOf: b)  // Swift 3
a.appendContentsOf(b)    // Swift 2
a.extend(b)              // Swift 1.2

print(a) // [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]

[Bất kỳ ai]? không giống với CGFloat. Trong khi nối với mảng AnyObject.
khun Sơn

6
Khun Sơn: AnyObjectchỉ ra một đối tượng, mà theo tôi hiểu có nghĩa là một cái gì đó được khởi tạo từ một loại lớp. CGFloatkhông phải là một đối tượng, nó là một giá trị vô hướng. Theo tôi hiểu, mảng có thể chứa vô hướng, trừ khi nó được định nghĩa là chứa AnyObjecthoặc được tinh chỉnh thêm. Tuy nhiên, tôi nghi ngờ ở đây vấn đề là mảng được gói trong một tùy chọn, vì vậy bạn phải mở khóa bằng !hoặc ?trước.
Owen Godfrey

Chúng ta có biết liệu trí thông minh Copy-On-Write của Swift 2 có mở rộng để xác định xem bphần của anó có bị sửa đổi hay không (do đó có thể tạo ra một bản sao btrong thời gian đó a.appendContentsOf(b)) không?
Ephemera

1
@OwenGodfrey cảm ơn. tôi có sự nhầm lẫn lil trên appendContentsOf và insertContentsOf.
khun Sơn


137

Với Swift 5, theo nhu cầu của bạn, bạn có thể chọn một trong sáu cách sau để nối / hợp nhất hai mảng.


# 1. Hợp nhất hai mảng thành một mảng mới với Array's +(_:_:)điều hành chung

Arraycó một +(_:_:)toán tử chung. +(_:_:)tuyên bố sau :

Tạo một bộ sưu tập mới bằng cách ghép các phần tử của một bộ sưu tập và một chuỗi.

static func + <Other>(lhs: Array<Element>, rhs: Other) -> Array<Element> where Other : Sequence, Self.Element == Other.Element

Mã mẫu Playground sau đây cho thấy cách hợp nhất hai mảng loại [Int]thành một mảng mới bằng +(_:_:)toán tử chung:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = array1 + array2
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 2. Nối các phần tử của một mảng thành một mảng hiện với Array's +=(_:_:)điều hành chung

Arraycó một +=(_:_:)toán tử chung. +=(_:_:)tuyên bố sau :

Nối các phần tử của chuỗi vào bộ sưu tập có thể thay thế phạm vi.

static func += <Other>(lhs: inout Array<Element>, rhs: Other) where Other : Sequence, Self.Element == Other.Element

Mã mẫu Playground sau đây cho thấy cách nối các phần tử của một loại kiểu [Int]vào một mảng hiện có bằng +=(_:_:)toán tử chung:

var array1 = [1, 2, 3]
let array2 = [4, 5, 6]

array1 += array2
print(array1) // prints [1, 2, 3, 4, 5, 6]

# 3. Nối một mảng vào mảng khác với Array's append(contentsOf:)phương pháp

Swift Arraycó một append(contentsOf:)phương pháp. append(contentsOf:)tuyên bố sau :

Thêm các yếu tố của một chuỗi hoặc bộ sưu tập vào cuối bộ sưu tập này.

mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element

Mã mẫu Playground sau đây cho thấy cách nối một mảng vào một mảng kiểu khác [Int]bằng append(contentsOf:)phương thức:

var array1 = [1, 2, 3]
let array2 = [4, 5, 6]

array1.append(contentsOf: array2)
print(array1) // prints [1, 2, 3, 4, 5, 6]

#4. Hợp nhất hai mảng thành một mảng mới với Sequence's flatMap(_:)phương pháp

Swift cung cấp một flatMap(_:)phương thức cho tất cả các loại phù hợp với Sequencegiao thức (bao gồm Array). flatMap(_:)tuyên bố sau :

Trả về một mảng chứa các kết quả được nối bằng cách gọi phép biến đổi đã cho với mỗi phần tử của chuỗi này.

func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

Mã mẫu Playground sau đây cho thấy cách hợp nhất hai mảng loại [Int]thành một mảng mới bằng flatMap(_:)phương thức:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = [array1, array2].flatMap({ (element: [Int]) -> [Int] in
    return element
})
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 5. Hợp nhất hai mảng thành một mảng mới với Sequence's joined()phương pháp và Array' s init(_:)initializer

Swift cung cấp một joined()phương thức cho tất cả các loại phù hợp với Sequencegiao thức (bao gồm Array). joined()tuyên bố sau :

Trả về các phần tử của chuỗi trình tự này, được nối.

func joined() -> FlattenSequence<Self>

Bên cạnh đó, Swift Arraycó một trình init(_:)khởi tạo. init(_:)tuyên bố sau :

Tạo một mảng chứa các phần tử của một chuỗi.

init<S>(_ s: S) where Element == S.Element, S : Sequence

Do đó, mã mẫu Playground sau đây cho thấy cách hợp nhất hai mảng loại [Int]thành một mảng mới bằng cách sử dụng joined()phương thức và trình init(_:)khởi tạo:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenCollection = [array1, array2].joined() // type: FlattenBidirectionalCollection<[Array<Int>]>
let flattenArray = Array(flattenCollection)
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 6. Hợp nhất hai mảng thành một mảng mới với Array's reduce(_:_:)phương pháp

Swift Arraycó một reduce(_:_:)phương pháp. reduce(_:_:)tuyên bố sau :

Trả về kết quả của việc kết hợp các phần tử của chuỗi bằng cách sử dụng bao đóng đã cho.

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

Mã Playground sau đây cho thấy cách hợp nhất hai mảng loại [Int]thành một mảng mới bằng reduce(_:_:)phương thức:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = [array1, array2].reduce([], { (result: [Int], element: [Int]) -> [Int] in
    return result + element
})
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

5
cảm ơn vì đã chia sẻ mã này, giải thích tốt, chỉ cần trả lời câu trả lời của bạn, nó sẽ là tốt nhất, nếu bạn nói cái nào hiệu quả hơn bằng hiệu suất?
kokemomuke

Tôi thích +cho 2 mảng và joined()cho một mảng các mảng.
Cœur

Nếu bạn hợp nhất nhiều hơn 2 mảng (hoặc chuỗi hoặc bất cứ thứ gì khác), hãy hạn chế sử dụng +toán tử, nó sẽ tạo ra thời gian biên dịch hoàn toàn điên rồ.
lawicko

@lawicko bạn sẽ giới thiệu phương pháp nào?
CyberMew

@CyberMew Bất cứ điều gì không sử dụng toán tử quá tải, tôi thích phương thức # 3 vì tôi nghĩ nó dễ đọc nhất, nhưng tôi cũng thích phương pháp số 4 với bản đồ phẳng. Đối với các chuỗi tôi thích phương thức # 5 vì cuối cùng, bạn nhận được chuỗi đã tham gia ngay lập tức.
lawicko

34

Nếu bạn không phải là một fan hâm mộ lớn của quá tải nhà điều hành, hoặc chỉ là một loại chức năng:

// use flatMap
let result = [
    ["merge", "me"], 
    ["We", "shall", "unite"],
    ["magic"]
].flatMap { $0 }
// Output: ["merge", "me", "We", "shall", "unite", "magic"]

// ... or reduce
[[1],[2],[3]].reduce([], +)
// Output: [1, 2, 3]

22

Phương pháp yêu thích của tôi kể từ Swift 2.0 là làm phẳng

var a:[CGFloat] = [1, 2, 3]
var b:[CGFloat] = [4, 5, 6]

let c = [a, b].flatten()

Điều này sẽ trở lại FlattenBidirectionalCollectionvì vậy nếu bạn chỉ muốn một CollectionTypeđiều này là đủ và bạn sẽ có đánh giá lười biếng miễn phí. Nếu bạn cần chính xác Mảng, bạn có thể làm điều này:

let c = Array([a, b].flatten())

2
flatten()ngày nay dường như không còn tồn tại nữa. Nhưng bạn có thể cân nhắc joined().
Cœur

13

Để hoàn thành danh sách các lựa chọn thay thế reducecó thể , có thể được sử dụng để thực hiện hành vi của flatten :

var a = ["a", "b", "c"] 
var b = ["d", "e", "f"]

let res = [a, b].reduce([],combine:+)

Cách thay thế tốt nhất (hiệu năng / bộ nhớ khôn ngoan) trong số những thứ được trình bày đơn giản flattenlà chỉ cần bọc các mảng ban đầu một cách lười biếng mà không tạo ra cấu trúc mảng mới.

Nhưng lưu ý rằng flatten không trả về a LazyCollection, do đó hành vi lười biếng sẽ không được truyền đến hoạt động tiếp theo dọc theo chuỗi (map, FlatMap, bộ lọc, v.v.).

Nếu sự lười biếng có ý nghĩa trong trường hợp cụ thể của bạn, chỉ cần nhớ thêm trước hoặc nối thêm .lazyvào flatten(), ví dụ, sửa đổi mẫu của Tomasz theo cách này:

let c = [a, b].lazy.flatten()

Làm thế nào tốt câu trả lời này vẫn còn tồn tại trong năm 2019 với Swift 5.1?
willbattel

flatten () không còn tồn tại nữa. tham gia () có thể được sử dụng thay vì flatten ()
Pranav Pravakar

4

Nếu bạn muốn chèn mảng thứ hai sau một chỉ mục cụ thể, bạn có thể thực hiện việc này (kể từ Swift 2.2):

let index = 1
if 0 ... a.count ~= index {
     a[index..<index] = b[0..<b.count]
}
print(a) // [1.0, 4.0, 5.0, 6.0, 2.0, 3.0] 

4

Swift 3.0

Bạn có thể tạo một mảng mới bằng cách thêm hai mảng hiện có với các loại tương thích với toán tử cộng ( +). Kiểu của mảng mới được suy ra từ kiểu của hai mảng bạn thêm vào với nhau,

let arr0 = Array(repeating: 1, count: 3) // [1, 1, 1]
let arr1 = Array(repeating: 2, count: 6)//[2, 2, 2, 2, 2, 2]
let arr2 = arr0 + arr1 //[1, 1, 1, 2, 2, 2, 2, 2, 2]

đây là kết quả đúng của các mã trên.


4
var arrayOne = [1,2,3]
var arrayTwo = [4,5,6]

nếu bạn muốn kết quả là: [1,2,3, [4,5,6]]

arrayOne.append(arrayTwo)

đoạn mã trên sẽ chuyển đổi mảngOne thành một phần tử duy nhất và thêm nó vào cuối mảngTwo.

nếu bạn muốn kết quả là: [1, 2, 3, 4, 5, 6] thì,

arrayOne.append(contentsOf: arrayTwo)

đoạn mã trên sẽ thêm tất cả các phần tử của mảngOne vào cuối mảngTwo.

Cảm ơn.


4

Swift 4.X

Cách dễ nhất tôi biết là chỉ sử dụng dấu +

var Array1 = ["Item 1", "Item 2"]
var Array2 = ["Thing 1", "Thing 2"]

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)

3

Đây là cách ngắn nhất để hợp nhất hai mảng.

 var array1 = [1,2,3]
 let array2 = [4,5,6]

Ghép / hợp nhất chúng

array1 += array2
New value of array1 is [1,2,3,4,5,6]

1

Tương tự, với từ điển của mảng người ta có thể:

var dict1 = [String:[Int]]()
var dict2 = [String:[Int]]()
dict1["key"] = [1,2,3]
dict2["key"] = [4,5,6]
dict1["key"] = dict1["key"]! + dict2["key"]!
print(dict1["key"]!)

và bạn có thể lặp lại trên dict1 và thêm dict2 nếu "khóa" khớp


0

Mảng Marge là các loại dữ liệu khác nhau:

var arrayInt = [Int]()
arrayInt.append(6)
var testArray = ["a",true,3,"b"] as [Any]
testArray.append(someInt)

Đầu ra:

["a", true, 3, "b", "hi", 3, [6]]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.