428

If there are two arrays created in swift like this:

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

How can they be merged to [1, 2, 3, 4, 5, 6]?

Hristo
  • 5,642
  • 3
  • 22
  • 35

13 Answers13

754

You can concatenate the arrays with +, building a new array

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

or append one array to the other with += (or 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]
Martin R
  • 488,667
  • 78
  • 1,132
  • 1,248
  • 1
    [AnyObect]? is not identical to CGFloat. While concatenating to AnyObject arrays. – khunshan Oct 02 '14 at 11:52
  • 6
    Khunshan: `AnyObject` indicates an object, which as I understand means something that is instantiated from a class type. `CGFloat` is not an object, it is a scalar value. As I understand it, arrays can contain scalars, unless it is defined as containing `AnyObject` or are further refined. However, I suspect here the problem is that the array is wrapped in an optional, so you have to unwrap it with `!` or `?` first. – Owen Godfrey Oct 14 '14 at 10:26
  • Do we know whether Swift 2's Copy-On-Write intelligence extends to determining whether the `b` part of `a` is modified (therefore possibly eliding a copy of `b` during `a.appendContentsOf(b)`)? – Ephemera Sep 20 '15 at 07:34
  • 1
    @OwenGodfrey thanks. i have lil confusion over appendContentsOf and insertContentsOf. – khunshan Jan 15 '16 at 07:10
  • [How can I combine two arrays each containing objects of different types](http://stackoverflow.com/q/35402692/1077789)? – Isuru Feb 15 '16 at 06:19
  • "appendContentsOf" always add the contents of the second array to the end of the first array, while "insertContentsOf" always inserts the contents of the second array at a designated position in the first, moving the contents of the first array at and after that point down the array to make roome for the contents of the second. – Owen Godfrey May 12 '16 at 07:11
  • What if I have two arrays holding objects and I want to combine them not repeating the existing items. E.g. let `array1 = [Obj1, Obj2, Obj3]`, `let array2 = [Obj1, Obj3, Obj4, Obj5]`. I want the result to be: `combinedArray = [Obj1, Obj2, Obj3, Obj4, Obj5]`. Any pointers? – oyalhi Sep 13 '16 at 15:13
  • @oyalhi: If you search for "remove duplicates from array" or "array of unique objects" then you should find something to start with. – Martin R Sep 13 '16 at 16:57
  • @MartinR sounds good. Thank you. In the mean time I filtered the second set from the first and then appended the first and second. – oyalhi Sep 14 '16 at 07:41
153

With Swift 5, according to your needs, you may choose one of the six following ways to concatenate/merge two arrays.


#1. Merge two arrays into a new array with Array's +(_:_:) generic operator

Array has a +(_:_:) generic operator. +(_:_:) has the following declaration:

Creates a new collection by concatenating the elements of a collection and a sequence.

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

The following Playground sample code shows how to merge two arrays of type [Int] into a new array using +(_:_:) generic operator:

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

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

#2. Append the elements of an array into an existing array with Array's +=(_:_:) generic operator

Array has a +=(_:_:) generic operator. +=(_:_:) has the following declaration:

Appends the elements of a sequence to a range-replaceable collection.

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

The following Playground sample code shows how to append the elements of an array of type [Int] into an existing array using +=(_:_:) generic operator:

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

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

#3. Append an array to another array with Array's append(contentsOf:) method

Swift Array has an append(contentsOf:) method. append(contentsOf:) has the following declaration:

Adds the elements of a sequence or collection to the end of this collection.

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

The following Playground sample code shows how to append an array to another array of type [Int] using append(contentsOf:) method:

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

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

#4. Merge two arrays into a new array with Sequence's flatMap(_:) method

Swift provides a flatMap(_:) method for all types that conform to Sequence protocol (including Array). flatMap(_:) has the following declaration:

Returns an array containing the concatenated results of calling the given transformation with each element of this sequence.

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

The following Playground sample code shows how to merge two arrays of type [Int] into a new array using flatMap(_:) method:

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. Merge two arrays into a new array with Sequence's joined() method and Array's init(_:) initializer

Swift provides a joined() method for all types that conform to Sequence protocol (including Array). joined() has the following declaration:

Returns the elements of this sequence of sequences, concatenated.

func joined() -> FlattenSequence<Self>

Besides, Swift Array has a init(_:) initializer. init(_:) has the following declaration:

Creates an array containing the elements of a sequence.

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

Therefore, the following Playground sample code shows how to merge two arrays of type [Int] into a new array using joined() method and init(_:) initializer:

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. Merge two arrays into a new array with Array's reduce(_:_:) method

Swift Array has a reduce(_:_:) method. reduce(_:_:) has the following declaration:

Returns the result of combining the elements of the sequence using the given closure.

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

The following Playground code shows how to merge two arrays of type [Int] into a new array using reduce(_:_:) method:

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]
Imanou Petit
  • 76,586
  • 23
  • 234
  • 201
  • 6
    thanks for sharing this code, good explanation, just adition to your answer, it would be best, if you say which one is more efficient by performance? – kokemomuke Jan 31 '17 at 05:14
  • I like `+` for 2 arrays and `joined()` for an array of arrays. – Cœur May 23 '19 at 03:56
  • If you're merging more than 2 arrays (or strings or whatever else), restrain yorself from using the `+` operator, it generates absolutely insane compile times. – lawicko Oct 21 '19 at 08:10
  • @lawicko which method will you recommend? – CyberMew Feb 13 '20 at 01:54
  • @CyberMew Anything that doesn't use overloaded operators, I like method #3 because I think it's most readable, but I also like method #4 with the flat map. For strings I like method #5 because at the end you get the joined string straight away. – lawicko Feb 13 '20 at 13:52
38

If you are not a big fan of operator overloading, or just more of a functional type:

// 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]
Community
  • 1
  • 1
Mazyod
  • 21,361
  • 9
  • 86
  • 147
24

My favorite method since Swift 2.0 is flatten

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

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

This will return FlattenBidirectionalCollection so if you just want a CollectionType this will be enough and you will have lazy evaluation for free. If you need exactly the Array you can do this:

let c = Array([a, b].flatten())
Tomasz Bąk
  • 5,764
  • 3
  • 31
  • 46
  • 3
    `flatten()` doesn't seem to exist anymore nowadays. But you may consider [`joined()`](https://developer.apple.com/documentation/swift/array/2945737-joined). – Cœur May 23 '19 at 04:00
17

To complete the list of possible alternatives, reduce could be used to implement the behavior of flatten:

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

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

The best alternative (performance/memory-wise) among the ones presented is simply flatten, that just wrap the original arrays lazily without creating a new array structure.

But notice that flatten does not return a LazyCollection, so that lazy behavior will not be propagated to the next operation along the chain (map, flatMap, filter, etc...).

If lazyness makes sense in your particular case, just remember to prepend or append a .lazy to flatten(), for example, modifying Tomasz sample this way:

let c = [a, b].lazy.flatten()
Cœur
  • 32,421
  • 21
  • 173
  • 232
Umberto Raimondi
  • 16,269
  • 7
  • 44
  • 54
5

Swift 4.X

easiest way I know is to just use the + sign

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

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)
Stotch
  • 161
  • 1
  • 8
4

If you want the second array to be inserted after a particular index you can do this (as of 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] 
Vitalii
  • 3,586
  • 29
  • 40
4

Swift 3.0

You can create a new array by adding together two existing arrays with compatible types with the addition operator (+). The new array's type is inferred from the type of the two array you add together,

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]

this is the right results of above codes.

X.Creates
  • 11,800
  • 7
  • 58
  • 98
4
var arrayOne = [1,2,3]
var arrayTwo = [4,5,6]

if you want result as : [1,2,3,[4,5,6]]

arrayOne.append(arrayTwo)

above code will convert arrayOne as a single element and add it to the end of arrayTwo.

if you want result as : [1, 2, 3, 4, 5, 6] then,

arrayOne.append(contentsOf: arrayTwo)

above code will add all the elements of arrayOne at the end of arrayTwo.

Thanks.

meMadhav
  • 225
  • 1
  • 11
3

Here's the shortest way to merge two arrays.

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

Concatenate/merge them

array1 += array2
New value of array1 is [1,2,3,4,5,6]
Jonathan
  • 23,467
  • 12
  • 62
  • 81
handiansom
  • 702
  • 11
  • 27
1

Similarly, with dictionaries of arrays one can:

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

and you can iterate over dict1 and add dict2 if the "key" matches

Jeremy Andrews
  • 697
  • 10
  • 15
0

Marge array that are different data types :

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

Output :

["a", true, 3, "b", "hi", 3, [6]]
Abhishek Gupta
  • 603
  • 5
  • 15
0

Swift 5 Array Extension

extension Array where Element: Sequence {
    func join() -> Array<Element.Element> {
        return self.reduce([], +)
    }
}

Example:

let array = [[1,2,3], [4,5,6], [7,8,9]]
print(array.join())

//result: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Li Jin
  • 953
  • 2
  • 8
  • 18