Problem overview
The method shout gets an array words of lowercase words and returns a new array in which every word is shouted: written in capital letters, with ! added after it. "hey" becomes "HEY!". The order stays the same, and a repeated word is shouted each time.
For ["hey", "you"] the result is ["HEY!", "YOU!"]. For ["go"] it is ["GO!"]. For ["no", "no", "no"] it is ["NO!", "NO!", "NO!"].
Approach
Every word turns into exactly one new word, in the same place. That is what map is for: it calls a function on each item and collects the answers in a new array of the same length. The function here takes a word and returns word.toUpperCase() + "!".
The same job with a loop needs an empty array, a for loop and a push for every word. map says the same thing in one line, and it leaves words as it was.
Here is the loop version, which gives the same result:
let shouted: string[] = [];
for (let word of words) {
shouted.push(word.toUpperCase() + "!");
}
Both are correct. map is shorter because it takes care of the empty array and the push for you, and this lesson is about using it.
Step by step
- Declare
shoutedas astring[]withletand set it towords.map(...). - Give
mapthe arrow functionword => word.toUpperCase() + "!". The methodtoUpperCase()returns the word in capitals, and+joins the"!"to its end. - Return
shouted.
The solution in TypeScript
class Solution {
shout(words: string[]): string[] {
let shouted: string[] = words.map(word => word.toUpperCase() + "!");
return shouted;
}
}
The arrow function has no braces, so its value is returned automatically. Adding braces would need an explicit return; without it, every item would become undefined.
Strings are immutable, so toUpperCase() doesn't change the word. It returns a new string, and map collects those new strings. For the same reason, words itself is unchanged after the call: with words = ["hey"], the result is ["HEY!"] and words still holds ["hey"].
Reading the arrow function
The part word => word.toUpperCase() + "!" is a small function with no name. Before the arrow comes its parameter; after it comes the value it gives back. map calls it once per item, passing the item in as word. TypeScript knows from the type of words that word is a string, so there's no need to write word: string. Two words in the input make two calls and two items in the output, which is why a repeated word like "no" is shouted each time it appears.
What happens with other input
The statement promises words made only of the letters a to z, so there is nothing else to handle. If a word already had capitals or digits, toUpperCase() would still work: it only changes letters that have a capital form. And a one-word array gives a one-word array, as in the ["go"] example.
Testing
| words | Result |
|---|---|
["hey", "you"] | ["HEY!", "YOU!"] |
["go"] | ["GO!"] |
["no", "no", "no"] | ["NO!", "NO!", "NO!"] |
These are the results of calling the method on the statement's examples. The result always has as many items as the input.
Common mistakes
- Calling
word.toUpperCase()without using the result. It returns the capitals and leaveswordalone. - Adding the
!to the whole array. The!belongs inside the arrow function, so each word gets its own. - Using
filterby mistake.filterchooses items,mapchanges them. Here nothing is dropped. - Braces without
return.word => { word.toUpperCase() + "!" }produces an array ofundefined.
