Problem overview
shout gets an ArrayBuffer[String] called words, with lowercase words. It returns a new buffer with every word shouted: in capital letters, with ! after it. The order stays the same.
["hey", "you"]gives["HEY!", "YOU!"].["go"]gives["GO!"].["no", "no", "no"]gives["NO!", "NO!", "NO!"], because a repeated word is shouted each time.
Approach
Every word becomes exactly one new word in the same place. That is what map is for. You write the change for one word, and map applies it to each word and collects the results in a new ArrayBuffer. The change is: make the word uppercase, then add "!" at the end.
Step by step
- Call
maponwordswith a function that turns eachwordintoword.toUpperCase + "!". Keep the result in avalnamedshouted. - Return
shouted.
The solution in Scala
class Solution {
def shout(words: ArrayBuffer[String]): ArrayBuffer[String] = {
val shouted = words.map(word => word.toUpperCase + "!")
return shouted
}
}
Details worth knowing:
toUpperCasereturns a new string. Strings can't be changed, soworditself stays lowercase. It is written without parentheses here;toUpperCase()works too and gives the same result.- The
+joins two strings. Without parentheses around the call,word.toUpperCase + "!"means "the uppercase word, then!". - The new buffer has as many items as
words. For the first example,shoutedhas 2 items. wordsis not changed.mapreturns a new buffer.
The same thing with a loop
Before map, you would build the result with a loop and an empty buffer:
val shouted = ArrayBuffer[String]()
for (word <- words) {
shouted += word.toUpperCase + "!"
}
For ["hey", "you"] this also gives ArrayBuffer(HEY!, YOU!). The loop and map do the same work: map creates the empty buffer, visits each item in order, adds one answer per item and hands the buffer back. When every item turns into exactly one new item, the one-line map says that directly, and there is nothing to get wrong in the setup.
Testing
["hey", "you"] ArrayBuffer(HEY!, YOU!)
["go"] ArrayBuffer(GO!)
["no", "no", "no"] ArrayBuffer(NO!, NO!, NO!)
Another way
Scala lets you shorten the function with an underscore: words.map(_.toUpperCase + "!") gives ArrayBuffer(HEY!, YOU!) for the first example. The underscore stands for the single argument. Naming it word, as the lesson does, is easier to read while you are learning.
Types and edge cases
The function's return type is ArrayBuffer[String]. Scala works out the type of shouted from the function you gave map: it returns a String for each word, so the result is an ArrayBuffer[String], and it matches the declared return type without any extra code.
The input always has at least one word, and every word uses only the letters a to z. That means there is nothing to special-case: no empty buffer, no digits or spaces. A word that is already in capitals would be unchanged by toUpperCase, so "Hey" would also become "HEY!".
The order of the two steps does not change the result here. Adding the ! first and then calling toUpperCase gives the same words, because the exclamation mark has no uppercase form.
Common mistakes
- Using
filter. Nothing is removed here. Every word must be in the result. - Forgetting the
!, or putting it before the word. It goes after. - Not saving the result.
words.map(...)alone doesn't changewords. Return the new buffer.
