ฉันจะเชื่อมต่อหรือผสานอาร์เรย์ใน Swift ได้อย่างไร


396

หากมีสองอาร์เรย์ที่สร้างขึ้นอย่างรวดเร็วเช่นนี้

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

พวกเขาจะรวมกันได้[1, 2, 3, 4, 5, 6]อย่างไร


นี่เป็นชุดย่อยของstackoverflow.com/q/24465281/78336
neoneye

คำตอบ:


691

คุณสามารถต่ออาร์เรย์เข้าด้วยกัน+เพื่อสร้างอาร์เรย์ใหม่

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

หรือผนวกหนึ่งอาร์เรย์ไปยังอีกอาร์เรย์หนึ่งด้วย+=(หรือ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]

[AnyObect] ไม่เหมือนกับ CGFloat ในขณะที่เชื่อมต่อกับอาร์เรย์ AnyObject
khunshan

6
Khunshan: AnyObjectระบุวัตถุซึ่งฉันเข้าใจหมายถึงบางสิ่งที่อินสแตนซ์จากประเภทคลาส CGFloatไม่ใช่วัตถุมันเป็นค่าสเกลาร์ ตามที่ฉันเข้าใจแล้วอาร์เรย์สามารถมีสเกลาร์ได้ยกเว้นว่ามีการกำหนดว่ามีAnyObjectหรือมีการกลั่นเพิ่มเติม อย่างไรก็ตามฉันสงสัยว่าที่นี่ปัญหาคือว่าอาร์เรย์ถูกรวมอยู่ในตัวเลือกดังนั้นคุณต้องแกะด้วย!หรือ?ก่อน
โอเว่นก็อดฟรีย์

เรารู้หรือไม่ว่าข่าวกรอง Copy-On-Write ของ Swift 2 นั้นครอบคลุมถึงการพิจารณาว่าbส่วนใดส่วนหนึ่งaได้รับการแก้ไขหรือไม่bช่วงa.appendContentsOf(b))?
แมลงเม่า

1
@OwenGodfrey ขอบคุณ ฉันมีความสับสน lil มากกว่า appendContentsOf และ insertContentsOf
คุนซาน


137

ด้วย Swift 5 ตามความต้องการของคุณคุณสามารถเลือกหนึ่งในหกวิธีต่อไปนี้เพื่อต่อ / ผสานสองอาร์เรย์


# 1 ผสานสองอาร์เรย์เป็นอาร์เรย์ใหม่กับArray's +(_:_:)ผู้ประกอบการทั่วไป

Arrayมี+(_:_:)ผู้ประกอบการทั่วไป +(_:_:)มีการประกาศดังต่อไปนี้:

สร้างคอลเลกชันใหม่โดยเชื่อมโยงองค์ประกอบของคอลเลกชันและลำดับ

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

โค้ดตัวอย่าง Playground ต่อไปนี้แสดงวิธีการรวมสองประเภทของอาร์เรย์[Int]เข้ากับอาร์เรย์ใหม่โดยใช้+(_:_:)ตัวดำเนินการทั่วไป:

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

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

# 2 ผนวกองค์ประกอบของอาร์เรย์เป็นอาร์เรย์ที่มีอยู่กับArray's +=(_:_:)ผู้ประกอบการทั่วไป

Array มี +=(_:_:)ผู้ประกอบการทั่วไป +=(_:_:)มีการประกาศดังต่อไปนี้:

ผนวกองค์ประกอบของลำดับไปยังคอลเลกชันที่เปลี่ยนช่วงได้

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

รหัสตัวอย่างสนามเด็กเล่นต่อไปนี้แสดงวิธีการผนวกองค์ประกอบของอาร์เรย์ประเภท[Int]ลงในอาร์เรย์ที่มีอยู่โดยใช้+=(_:_:)ตัวดำเนินการทั่วไป:

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

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

# 3 ผนวกอาร์เรย์อาร์เรย์อีกด้วยArray's append(contentsOf:)วิธี

สวิฟท์Arrayมีappend(contentsOf:)วิธีการ append(contentsOf:)มีดังต่อไปนี้ประกาศ :

เพิ่มองค์ประกอบของลำดับหรือคอลเลกชันที่ส่วนท้ายของคอลเลกชันนี้

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

โค้ดตัวอย่าง Playground ต่อไปนี้แสดงวิธีผนวกอาร์เรย์ไปยังอาร์เรย์ประเภทอื่น[Int]โดยใช้append(contentsOf:)วิธีการ:

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

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

# 4 ผสานสองอาร์เรย์เข้ากับอาร์เรย์ใหม่ด้วยSequence 's flatMap(_:)วิธี

Swift มีflatMap(_:)วิธีการสำหรับทุกประเภทที่สอดคล้องกับSequenceโปรโตคอล (รวมถึงArray) flatMap(_:)มีการประกาศดังต่อไปนี้:

ส่งคืนอาร์เรย์ที่มีผลลัพธ์ที่ต่อกันของการเรียกการแปลงที่กำหนดกับแต่ละองค์ประกอบของลำดับนี้

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

รหัสตัวอย่างสนามเด็กเล่นต่อไปนี้แสดงวิธีการผสานสองชนิดของอาร์เรย์[Int]ลงในอาร์เรย์ใหม่โดยใช้flatMap(_:)วิธีการ:

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 ผสานสองอาร์เรย์เป็นอาร์เรย์ใหม่กับSequence'sjoined()วิธีการและArray' s init(_:)initializer

Swift ให้joined()วิธีการสำหรับทุกประเภทที่สอดคล้องกับSequenceโปรโตคอล (รวมถึงArray) joined()มีการประกาศดังต่อไปนี้:

ส่งคืนองค์ประกอบของลำดับของลำดับนี้เรียงต่อกัน

func joined() -> FlattenSequence<Self>

นอกจากนี้ Swift Arrayยังมีตัวตั้งinit(_:)ค่าเริ่มต้น init(_:)มีการประกาศดังต่อไปนี้ :

สร้างอาร์เรย์ที่มีองค์ประกอบของลำดับ

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

ดังนั้นรหัสตัวอย่างสนามเด็กเล่นต่อไปนี้แสดงวิธีผสานสองประเภทอาร์เรย์[Int]เข้าในอาร์เรย์ใหม่โดยใช้joined()วิธีการและเครื่องมือinit(_:)เริ่มต้น:

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 ผสานสองอาร์เรย์เป็นอาร์เรย์ใหม่กับArray's reduce(_:_:)วิธี

สวิฟท์Arrayมีreduce(_:_:)วิธีการ reduce(_:_:)มีดังต่อไปนี้ประกาศ :

ส่งคืนผลลัพธ์ของการรวมองค์ประกอบของลำดับโดยใช้การปิดที่กำหนด

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

รหัส Playground ต่อไปนี้แสดงวิธีการรวมสองประเภทของอาร์เรย์[Int]ลงในอาร์เรย์ใหม่โดยใช้reduce(_:_:)วิธีการ:

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
ขอบคุณสำหรับการแบ่งปันรหัสนี้คำอธิบายที่ดีเพียงคำตอบของคุณจะดีที่สุดถ้าคุณบอกว่าประสิทธิภาพใดมีประสิทธิภาพมากกว่ากัน
kokemomuke

ฉันชอบ+2 อาร์เรย์และjoined()สำหรับอาร์เรย์
Cœur

หากคุณกำลังรวมมากกว่า 2 อาร์เรย์ (หรือสตริงหรือสิ่งอื่นใด) ห้ามไม่ให้คุณใช้+โอเปอเรเตอร์มันจะสร้างเวลาในการคอมไพล์อย่างบ้าคลั่ง
lawicko

@lawicko คุณจะแนะนำวิธีใด
CyberMew

@CyberMew อะไรก็ตามที่ไม่ได้ใช้โอเปอเรเตอร์ที่โอเวอร์โหลดฉันชอบวิธีที่ # 3 เพราะฉันคิดว่ามันอ่านง่ายที่สุด แต่ฉันก็ชอบวิธีที่ # 4 ด้วยแผนที่แบน สำหรับสตริงที่ฉันชอบวิธี # 5 เพราะในตอนท้ายคุณจะได้สตริงที่เข้าร่วมทันที
lawicko

34

หากคุณไม่ใช่แฟนตัวยงของผู้ให้บริการมากไปหรือเป็นประเภทการใช้งานมากกว่า:

// 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

วิธีการโปรดของฉันตั้งแต่ Swift 2.0 แบน

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

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

สิ่งนี้จะส่งคืนFlattenBidirectionalCollectionดังนั้นหากคุณต้องการเพียงแค่CollectionTypeนี้ก็เพียงพอแล้วและคุณจะมีการประเมินผลแบบไม่คิดค่าใช้จ่าย หากคุณต้องการอาเรย์ที่แน่นอนคุณสามารถทำได้:

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

2
flatten()ดูเหมือนจะไม่มีอีกต่อไปในปัจจุบัน joined()แต่คุณอาจจะพิจารณา
Cœur

13

เพื่อทำให้รายการทางเลือกที่เป็นไปได้สมบูรณ์reduceสามารถนำมาใช้เพื่อทำให้พฤติกรรมของแบนราบ :

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

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

ทางเลือกที่ดีที่สุด (ประสิทธิภาพ / หน่วยความจำที่ชาญฉลาด) ในบรรดาสิ่งที่นำเสนอคือเพียงflattenแค่ห่ออาร์เรย์ดั้งเดิมอย่างเกียจคร้านโดยไม่ต้องสร้างโครงสร้างอาร์เรย์ใหม่

แต่สังเกตเห็นว่าเรียบ ไม่กลับLazyCollectionเพื่อให้พฤติกรรมขี้เกียจจะไม่ได้แพร่กระจายไปยังการดำเนินการต่อไปพร้อมโซ่ (แผนที่ flatMap กรอง ฯลฯ ... )

หาก lazyness ทำให้ความรู้สึกในกรณีของคุณโดยเฉพาะก็อย่าลืมย่อหน้าหรือผนวก.lazyไปflatten()ตัวอย่างเช่นการปรับเปลี่ยนตัวอย่าง Tomasz วิธีนี้:

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

คำตอบนี้ดีแค่ไหนที่ยังคงอยู่ในปี 2019 ด้วย Swift 5.1
willbattel

แบน () ไม่มีอยู่อีกแล้ว เข้าร่วม () สามารถใช้แทนการแบน ()
รานาฟปราสคาร์

4

หากคุณต้องการให้อาร์เรย์ที่สองถูกแทรกหลังจากดัชนีเฉพาะคุณสามารถทำได้ (ตั้งแต่ 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

คุณสามารถสร้างอาร์เรย์ใหม่ได้โดยเพิ่มอาร์เรย์ที่มีอยู่สองชุดพร้อมกับประเภทที่เข้ากันได้กับตัวดำเนินการเพิ่ม ( +) ประเภทของอาร์เรย์ใหม่ถูกอนุมานจากประเภทของสองอาร์เรย์ที่คุณเพิ่มเข้าด้วยกัน

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]

นี่คือผลลัพธ์ที่ถูกต้องของโค้ดด้านบน


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

ถ้าคุณต้องการผลลัพธ์เป็น: [1,2,3, [4,5,6]]

arrayOne.append(arrayTwo)

โค้ดด้านบนจะแปลง arrayOne เป็นองค์ประกอบเดียวและเพิ่มไปยังจุดสิ้นสุดของ arrayTwo

ถ้าคุณต้องการผลเป็น: [1, 2, 3, 4, 5, 6] แล้ว

arrayOne.append(contentsOf: arrayTwo)

โค้ดด้านบนจะเพิ่มองค์ประกอบทั้งหมดของ arrayOne ที่ส่วนท้ายของ arrayTwo

ขอบคุณ


4

Swift 4.X

วิธีที่ง่ายที่สุดที่ฉันรู้คือแค่ใช้เครื่องหมาย +

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

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)

3

นี่คือวิธีที่สั้นที่สุดในการผสานสองอาร์เรย์

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

เชื่อมต่อ / รวมเข้าด้วยกัน

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

1

ในทำนองเดียวกันพจนานุกรมมีอาร์เรย์หนึ่งที่สามารถ:

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"]!)

และคุณสามารถวนซ้ำ dict1 และเพิ่ม dict2 หาก "คีย์" ตรงกัน


0

อาร์เรย์มาร์จที่เป็นประเภทข้อมูลที่แตกต่างกัน:

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

ผลผลิต:

["a", true, 3, "b", "hi", 3, [6]]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.