Problem overview
The function getFullNames receives a slice of strings, names, in which first names and last names alternate: a first name, then its last name, then the next first name, and so on. It returns a new slice of full names, each first name joined to its last name with one space.
For ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"] the pairs are John and Doe, Andy and Smith, Mary and Johnson. The result is ["John Doe", "Andy Smith", "Mary Johnson"]. The result has half as many elements as the input.
Approach: visit every second element
Every full name starts at an even index: 0, 2, 4, and so on. The last name is always at the next index. So a loop that moves by 2 lands on each first name exactly once, and the element after it is the matching last name.
For each such index i, join names[i], a space and names[i+1], and add the result to a slice that the function returns at the end.
Step by step
- Create the result slice. Declare
answeras an empty slice of strings. It can start empty becauseappendgrows it as needed. - Loop over even indices. Use a
forloop withistarting at 0 and a step ofi += 2, soialways points at a first name. - Build the full name. Inside the loop, declare
nameasnames[i]plus a space plusnames[i+1]. The+operator joins strings. - Save it. Append
nametoanswerand assign the result back toanswer. - Return after the loop. Returning inside the loop would end the function after the first pair.
The solution in Go
func getFullNames(names []string) []string {
answer := []string{}
for i := 0; i < len(names); i += 2 {
name := names[i] + " " + names[i+1]
answer = append(answer, name)
}
return answer
}
Go details to notice:
- The loop step. The post statement of a
forcan be any simple statement, soi += 2works just asi++does. There is no separate "step" syntax. appendreturns a slice. It may have to allocate a bigger backing array, so it hands back the updated slice. Callingappend(answer, name)and ignoring the result is a compile error, and writinganswer = append(answer, name)is the only correct form.[]string{}againstnil.[]string{}is an empty, non-nil slice, whilevar answer []stringis anilslice. Both have length 0, print as[], and work withappend. The lesson starts from the empty literal, so an empty input returns a slice that is empty but notnil.- Strings join with
+.names[i] + " " + names[i+1]creates a new string. The space is a string literal in double quotes. A single-quoted' 'would be a rune, which can't be added to a string. :=in the loop.nameis a fresh variable on every iteration, because the declaration is inside the loop body.
Complexity
Let n be the length of names.
Time: O(n). The loop runs n / 2 times. Each pass joins two strings and appends one element. Appending is cheap on average, since the slice grows in large steps.
Space: O(n). The result holds n / 2 strings, each about as long as the two names combined.
Edge cases and common mistakes
- Empty input. With no names the loop never runs and the function returns an empty slice.
- Odd length. The lesson's input always has pairs. If the length were odd, such as
["a", "b", "c"], the last pass would readnames[3]and Go would stop with a run-time panic:index out of range [3] with length 3. Go checks every index, so an overrun is never silent. - Stepping by 1. With
i++, the loop would pair "Doe" with "Andy" and produce twice as many results, mostly wrong ones. - Forgetting the space.
names[i] + names[i+1]givesJohnDoe. - Dropping the assignment of
append. The compiler rejects it, and it is a reminder that slices are values: the old variable still describes the old slice. - Returning inside the loop. Only the first full name would come back.
Testing
["John", "Doe", "Andy", "Smith", "Mary", "Johnson"]gives["John Doe", "Andy Smith", "Mary Johnson"].["Ada", "Lovelace"]gives["Ada Lovelace"].[]gives[].