Як з'єднати чи злити масиви в Swift?


Відповіді:


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або додатково уточнені. Однак я підозрюю, що проблема полягає в тому, що масив загорнуто в необов'язковий, тому вам доведеться розгортати його !або ?спочатку
Оуен Годфрі

Як ми знаємо , чи поширюється Swift 2 в Copy-On-Write розвідки для визначення , є чи bчастина aмодифікуються (тому , можливо , eliding копії 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

Наведений нижче зразок коду дитячої площадки показує, як об’єднати два масиви типу [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 +=(_:_:)generic

Arrayмає +=(_:_:)загальний оператор. +=(_:_:)має таку заяву :

Додає елементи послідовності до колекції, що змінюється діапазоном.

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

Наведений нижче зразок коду Playground показує, як додати елементи масиву типу [Int]до існуючого масиву за допомогою +=(_:_:)загального оператора:

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

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

№3. Додайте масив до іншого масиву методом Arraysappend(contentsOf:)

У Свіфта Arrayє append(contentsOf:)метод. append(contentsOf:)має таку заяву :

Додає елементи послідовності чи колекції до кінця цієї колекції.

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

Наведений нижче зразок коду дитячої площадки показує, як додати масив до іншого типу масиву за [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. Об’єднайте два масиви в новий масив методом SequencesflatMap(_:)

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«S joined()методом і Array» s init(_:)ініціалізатор

Swift пропонує joined()метод для всіх типів, які відповідають Sequenceпротоколу (включаючи Array). joined()має таку заяву :

Повертає елементи цієї послідовності послідовних послідовностей.

func joined() -> FlattenSequence<Self>

Крім того, у Swift Arrayє init(_:)ініціалізатор. init(_:)має таку заяву :

Створює масив, що містить елементи послідовності.

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

Тому наступний зразок коду Playground показує, як об’єднати два масиви типу [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. Об’єднайте два масиви в новий масив методом Arraysreduce(_:_:)

У Свіфта Arrayє reduce(_:_:)метод. reduce(_:_:)має таку заяву :

Повертає результат поєднання елементів послідовності за допомогою заданого замикання.

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

Наведений нижче код майданчика показує, як об’єднати два масиви типу [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

Якщо ви об'єднуєте більше двох масивів (або рядків чи будь-чого іншого), не обмежуйте використання +оператора, це генерує абсолютно божевільні рази компіляції.
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, що просто ліниво обернути початкові масиви, не створюючи нової структури масиву.

Але зауважте, що flatten не повертає a LazyCollection, так що лінива поведінка не буде поширюватися на наступну операцію по ланцюгу (карта, flatMap, фільтр тощо).

Якщо ленивости мають сенс у вашому конкретному випадку, тільки НЕ забудьте додати препенд або .lazyдо flatten(), наприклад, зміна Tomasz Sample наступним чином:

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

Наскільки добре ця відповідь все ще стоїть у 2019 році за допомогою Swift 5.1?
willbattel

flatten () вже не існує. joined () можна використовувати замість flatten ()
Pranav Pravakar

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 в кінці масивуTwo.

Дякую.


4

Швидкий 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]]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.