Start learning free

LESSON 183 OF 414 · LOOPS - CHALLENGES

Get Full Names II in Scala: Pairing Names with a Step of 2

Practice Read the full explanation

Given an array of strings names that contain first and last names adjacent to each other, return a list 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

    SCALA · LOOPS - CHALLENGES

    Get Full Names 2 in Scala, explained

    Problem overview

    The method getFullNames(names: Array[String]) receives an array in which every first name is directly followed by its last name. It returns a List[String] with one full name per pair, joined by a single space.

    For ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"] the pairs are John Doe, Andy Smith and Mary Johnson, so the result is List(John Doe, Andy Smith, Mary Johnson). Six names produce three full names.

    Approach

    First names sit at the even indices 0, 2, 4, and so on, and each last name sits right after its first name, at i + 1. So the loop does not need to visit every index: it visits only the even ones, and at each stop it joins names(i) and names(i + 1). In Scala that is a range with a step: 0 until names.size by 2.

    The results have to be collected somewhere. The array's size is fixed and the final count (half the input) is known, but a growable buffer is the simplest tool, and the method converts it to the required List at the end.

    Step by step

    1. Create an empty ArrayBuffer[String]. It is a mutable, growable sequence. The full path scala.collection.mutable.ArrayBuffer avoids an import. The name answer can be a val, because the variable never points to another buffer, even though the buffer's contents change.
    2. Loop over the even indices. for (i <- 0 until names.size by 2) produces 0, 2, 4, ... The by 2 sets the step, and until excludes the end, so for six names i is 0, 2 and 4.
    3. Build one full name. names(i) + " " + names(i + 1) joins the first name, a space and the last name.
    4. Append it. answer += name adds the string to the end of the buffer, which keeps the pairs in input order.
    5. Convert and return after the loop. answer.toList copies the buffer into an immutable List, the type in the method's signature. Returning inside the loop would end it after the first pair.

    The solution in Scala

    class Solution {
        def getFullNames(names: Array[String]): List[String] = {
            val answer = scala.collection.mutable.ArrayBuffer[String]()
            for (i <- 0 until names.size by 2) {
                val name = names(i) + " " + names(i + 1)
                answer += name
            }
            return answer.toList
        }
    }
    

    Some Scala details:

    • Ranges with a step. 0 until 6 by 2 is the range 0, 2, 4. 0 to 6 by 2 would also include 6, which would be one step too far for this problem.
    • Arrays use parentheses. names(i) reads an element. In Scala, indexing is a method call (apply), so there are no square brackets.
    • val with a mutable object. val answer cannot be reassigned, but answer += name calls a method on the same buffer, so it still works. (With a var and an immutable List, you would write answer = answer :+ name, which copies the list on every append.)
    • size and length. On an Array both give the number of elements.
    • Immutable result. A List cannot be changed after it is built, so the caller cannot accidentally modify the answer through the buffer.

    Complexity

    Let n be the length of names.

    Time: O(n). The loop runs n / 2 times. Each pass joins two short strings and appends to the buffer in amortized constant time. toList then copies the n / 2 results once.

    Space: O(n). The buffer and the list hold n / 2 strings each. The strings themselves are new, because each full name is a fresh string.

    Edge cases and common mistakes

    • Empty array. 0 until 0 by 2 is empty, so the method returns an empty list.
    • Odd length. The statement guarantees pairs, so the length is even. With an odd length, the last index i would make names(i + 1) fail with an ArrayIndexOutOfBoundsException. For ["A", "B", "C"] the method throws on the second pass.
    • Stepping by 1. Looping over every index would pair Doe with Andy and produce six strings, not three.
    • Missing space. The separator must be exactly one space: "John" + "Doe" gives JohnDoe.
    • Returning the buffer. An ArrayBuffer is not a List, so the method needs toList to satisfy its declared return type.

    Testing

    • Array("John", "Doe", "Andy", "Smith", "Mary", "Johnson") gives List(John Doe, Andy Smith, Mary Johnson).
    • Array("A", "B", "C", "D") gives List(A B, C D).
    • Array() gives List().
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free