Как объединить или объединить массивы в 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.
Хуншан

6
Кхуншан: AnyObjectуказывает на объект, который, как я понимаю, означает что-то, что создается из типа класса. CGFloatэто не объект, это скалярное значение. Насколько я понимаю, массивы могут содержать скаляры, если они не определены как содержащие AnyObjectили не уточняются. Тем не менее, я подозреваю, что здесь проблема заключается в том, что массив обернут в необязательный, поэтому вы должны развернуть его !или ?сначала.
Оуэн Годфри

Как мы знаем , распространяется ли Swift 2 в Copy-On-Write разведки для определения , является ли bчасть aмодифицируются (поэтому , возможно , eliding копии bво время a.appendContentsOf(b))?
Эфемера

1
@OwenGodfrey спасибо. У меня путаница по поводу 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«ы +=(_:_:)общего оператора

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. Append массива в другой массив с 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

В следующем примере кода Playground показано, как объединить два массива типа [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. Объединить два массива в новый массив с 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,

Если вы объединяете более двух массивов (или строк, или чего-либо еще), воздержитесь от использования +оператора, это приведет к абсолютно безумному времени компиляции.
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этого будет достаточно, и вы будете иметь ленивую оценку бесплатно. Если вам нужен именно Array, вы можете сделать это:

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

2
flatten()кажется, больше не существует в наши дни. Но вы можете рассмотреть joined().
Cœur

13

Чтобы завершить список возможных альтернатив, reduceможно было бы использовать поведение flatten :

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

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

Лучшая альтернатива (с точки зрения производительности / памяти) среди представленных - просто flattenлениво оборачивать исходные массивы без создания новой структуры массива.

Но обратите внимание, что сглаживать не возвращается a LazyCollection, так что ленивое поведение не будет распространяться на следующую операцию по цепочке (map, flatMap, filter и т. Д.).

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

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

Насколько хорошо этот ответ остается в 2019 году с Swift 5.1?
Willbattel

flatten () больше не существует.
join

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

Массив Marge, которые имеют разные типы данных:

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.