Start learning free

LESSON 184 OF 415 · LOOPS - CHALLENGES

Get Full Names II in Swift: Looping in Pairs with stride

Practice Read the full explanation

Given an array of strings names that contain first and last names adjacent to each other, return an array containing the full names (separated by one space)

Example:

Input:  names = ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"]

Output:  ["John Doe", "Andy Smith", "Mary Johnson"]
STEP 1 OF 5
    Ctrl + Enter to check

    SWIFT · LOOPS - CHALLENGES

    Get Full Names 2 in Swift, explained

    Problem overview

    The method getFullNames(_ names: [String]) receives an array in which first names and last names sit next to each other: the first name at an even index, its last name right after it. It returns a new array with the full names, each first and last name joined by one space.

    For ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"] the result is ["John Doe", "Andy Smith", "Mary Johnson"]. Six strings in, three strings out.

    Approach

    The input is made of pairs, so the loop should move through it two positions at a time instead of one. If i is the index of a first name, then names[i + 1] is its last name. Stepping i through 0, 2, 4, and so on visits each pair exactly once. Build the full name from the two strings, add it to a result array, and return that array.

    Step by step

    1. Create the result array. var answer = [String]() starts empty. It needs var because it grows in the loop.
    2. Loop over the even indices with stride(from: 0, to: names.count, by: 2). It produces 0, 2, 4, and stops before names.count. The upper bound is excluded, like in a half-open range.
    3. Join the pair. names[i] + " " + names[i + 1] concatenates the first name, one space and the last name into a constant name.
    4. Append it with answer.append(name). Appending at the end keeps the output in the same order as the input pairs.
    5. Return after the loop. A return inside the loop would send back only the first full name.

    The solution in Swift

    class Solution {
        func getFullNames(_ names: [String]) -> [String] {
            var answer = [String]()
            for i in stride(from: 0, to: names.count, by: 2) {
                let name = names[i] + " " + names[i + 1]
                answer.append(name)
            }
            return answer
        }
    }
    

    Swift details:

    • stride instead of a range. Ranges like 0..<n always step by 1. stride(from:to:by:) is the function for other step sizes. Use stride(from:through:by:) when the end value should be included. Swift has no C-style for (i = 0; i < n; i += 2) loop.
    • Arrays of strings. [String]() creates an empty array of strings, equivalent to var answer: [String] = [].
    • The + operator joins strings, including the space literal in the middle. String interpolation, "\(names[i]) \(names[i + 1])", gives the same result.
    • Value semantics. The result is a new array. The input is not modified.

    to versus through

    The difference between the two stride forms is easy to see with six elements. stride(from: 0, to: 6, by: 2) yields 0, 2, 4, while stride(from: 0, through: 6, by: 2) yields 0, 2, 4, 6. Since 6 is not a valid index of a six-element array, the lesson uses to:. The valid indices always stop at names.count - 1, and to: excludes its bound just as 0..<names.count does.

    The loop could also run over the pair count instead of the index: for k in 0..<names.count / 2 with names[2 * k] and names[2 * k + 1]. It gives the same result, but with stride the index you use is the index you read, which is simpler to follow.

    Complexity

    Time: O(n) for n names. The loop runs n / 2 times and builds one string per pair, in time proportional to the characters involved. Space: O(n), because the result holds n / 2 strings.

    Edge cases and common mistakes

    • Empty input. stride(from: 0, to: 0, by: 2) produces nothing, so the method returns [].
    • An odd number of names. The method assumes complete pairs. With three names, the last pass reads names[3], which doesn't exist, and the program stops with an index-out-of-range error. The task's input always has pairs.
    • Stepping by 1. A plain for i in 0..<names.count would pair every name with the following one, giving overlapping results like "Doe Andy".
    • Missing space. names[i] + names[i + 1] gives "JohnDoe".
    • Using to: and through: interchangeably. With through: names.count the last pass would start past the end of the array and crash.

    Testing

    • ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"] gives ["John Doe", "Andy Smith", "Mary Johnson"].
    • [] gives [].
    • ["A", "B"] gives ["A B"].
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free