0

I'm looking to append the values of two arrays by their respective positions [0] and [1]. For example - firstArray = [“John”, “Sam”] and secondArray = [“Smith”, “Thomas”].

I would like the output to read as John Smith and Sam Thomas.

I've tried creating a loop to loop through as shown below:

import UIKit

var firstArray = ["John", "Tim"]
var secondArray = ["Smith"]

for i in firstArray.count - 1 {
let name = firstArray[i] + secondArray[i]
}

Error message: Type 'Int' does not conform to protocol 'Sequence'

3 Answers3

1

The correct syntax of a for loop is:

for [VARIABLE_NAME] in [SEQUENCE] {

}

In this case it could be

for i in 0...(firstArray.count - 1) { }

or

for i in 0..<firstArray.count { }

To merge both arrays, you could do:

let firstArray = ["John", "Sam"]
let secondArray = ["Smith",]

var names = zip(firstArray, secondArray).map { $0 + " " + $1 }

If you want to add the rest of the longer array:

if firstArray.count < secondArray.count {
    names.append(contentsOf: secondArray[firstArray.count...])
} else if secondArray.count < firstArray.count {
    names.append(contentsOf: firstArray[secondArray.count...])
}

print(names)    //["John Smith", "Sam"]

Finally, you could join them this way:

let joinedNames = names.joined(separator: " and ")  //John Smith and Sam

More generically, you could merge any number of arrays this way:

func zigzag<T>(through arrays: [[T]]) -> [T] {
    var result = [T]()
    var index = 0

    while true {
        var didAppend = false
        for array in arrays {
            if index < array.count {
                result.append(array[index])
                didAppend = true
            }
        }
        if didAppend == false { break }
        index += 1
    }

    return result
}

For example:

zigzag(through: [[11, 12], [21, 22, 23, 24], [31, 32, 33]])

//[11, 21, 31, 12, 22, 32, 23, 33, 24]
ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • I think that this is a really good answer with a single exception, a for loop iterates over a sequence rather than a range. A range is a sequence but there are others as well including sequences that are tuples. – Michael Salmon Aug 21 '19 at 18:40
  • @MichaelSalmon Thank you for the heads-up! – ielyamani Aug 21 '19 at 18:42
  • 1
    Thank you for the thorough reply!! Its greatly appreciated. @ielyamani – NoobLearns Aug 21 '19 at 19:28
  • @ielyamani I just found out that for loops can have a where clause which works really well when you have a for loop with a single if. It isn't mentioned in the guide but it is in the reference. IMHO it is much easier to read and saves a level of indentation. – Michael Salmon Aug 25 '19 at 06:54
0

You can use firstArray.indices which is a range or 0..<firstArray.count although that doesn't always work as not all arrays start at 0 and count can be expensive. firstArray.count - 1 is a single value, not a sequence of values. You can also do things like let names: [String] = firstArray.indices.map { firstArray[$0] + secondArray[$0] } which IMHO is really cool.

Michael Salmon
  • 1,056
  • 7
  • 15
  • Thanks @Micheal Salmon for taking the time to reply. Unfortunately, the code is throwing an error. EXC_BAD_INSTRUCTION (Code=EXC_I386_INVOP, subcode=0x0)..... This is the code >>>>> import UIKit var firstArray = ["John", "Tim"] var secondArray = ["Smith"] for i in firstArray.indices { let names = firstArray[i] + secondArray[i] } Any suggestions? I've also tried let names: [String] = firstArray.indices.map { firstArray[$0] + secondArray[$0] } to no avail. – NoobLearns Aug 21 '19 at 18:15
  • I like the zip solution better than mine. – Michael Salmon Aug 21 '19 at 18:20
  • I ran the code in Swift Playground, both the for loop and the map. Both ran without problem. You example has a bug by the way, secondArray has only a single entry. – Michael Salmon Aug 21 '19 at 18:32
  • Thanks for your help @MichealSalmon. I wasn't sure if both arrays that were being evaluated needed to have an identical number of entries. – NoobLearns Aug 21 '19 at 19:33
0

The best way to do this might be to use zip and map.

Say you have your arrays of first and last names:

let firstNames = ["John", "Sam", "Phil"]
let lastNames = ["Smith", "Thompson"]

let fullNames = zip(firstNames, lastNames).map { first, last in
   return "\(first) \(last)"
}

It will only combine as far as the sequence that ends first, so in this example, you would get back ["John Smith", "Sam Thompson"].

kid_x
  • 1,415
  • 1
  • 11
  • 31