-3

so I've wrote this function, i want to uppercase the vowels and lowercase every other letter, problem the end result ends with the same string, I'm new to spread and for-each, after i spread a string does it become an array? when i manipulate letters does it suppose to become a string again with the manipulations or do i need to join it? why aren't the upper and lowercase functions don't work?

the function:

function upperCase(str) {
  var vowels = "aeiou";
  [...str].forEach(letter => {
    if (vowels.includes(letter)) letter.toUpperCase();
    letter.toLowerCase();
  });
  console.log(str);
}
  • Don't ever use `forEach`. And notice that `toUpperCase()` does not change a string (or char), it returns a new one. So build a new string that you can `return` (or log) in the end. – Bergi Feb 03 '20 at 20:37
  • "*after i spread a string does it become an array?*" - yes, you are spreading inside an array literal – Bergi Feb 03 '20 at 20:38
  • Taplar, that is incorrect, Begi- why shouldn't i use for-each? and so basically i need to creat an empty string and add to it? im unable to manipulate the given string to something else? –  Feb 03 '20 at 20:40
  • Yes, [avoid foreach](https://stackoverflow.com/a/49420944/1048572), [use for...of](https://stackoverflow.com/a/50844413/1048572) instead (then you don't even need to spread into an array), or `map` to a new array and then `.join("")` the letters back to a string. – Bergi Feb 03 '20 at 20:41

3 Answers3

3

You have several problems:

  1. .toUpperCase and toLowerCase return the new value, they don't mutate the existing value (and strings are immutable anyway)
  2. Even if they did mutate the existing value, they'd change the letter string in the array and not the original string
  3. You didn't use else to toLowerCase always runs

You need to:

  1. return a value
  2. Use map to collect the values
  3. Use join() to turn the array back into a string

Such:

function upperCase(str) {
  const vowels = "aeiou";
  const result = 
      [...str]
          .map(
              letter => 
                  (vowels.includes(letter)) 
                  ? letter.toUpperCase() 
                  : letter.toLowerCase()
           ).join("");
  console.log(result);
}

upperCase("The quick brown fox jumps over the lazy dog");
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

You need to assign the result of your foreach to something.

function upperCase(str) {
  var vowels = "aeiou";
  [...str].forEach(letter => {
    if (vowels.includes(letter)) letter.toUpperCase();
    letter.toLowerCase();
  });
  console.log(str);
}

[...str] is creating an array, looping over it, preforming an action, but then not saving the resulting array to any variable at the end. You're also missing an else and/ or a return. I think a map also makes more sense in this case.

function upperCase(str) {
  var vowels = "aeiou";
  const result = [...str].map(letter => {
    if (vowels.includes(letter)) return letter.toUpperCase();
   return letter.toLowerCase();
  });
  console.log(result);
}
Cal Irvine
  • 1,104
  • 8
  • 17
  • so its impossible to save with a foreach loop? i need to use map to creat a new array to save to? thanks –  Feb 03 '20 at 20:42
  • @AntiMatter foreach can manipulate the original array. Either can be used, but typically when performing manipulations on an array, you want to return a new array reference. It depends, there are use cases for both. I just feel the .map is more what you're looking for in this case. As said above in a comment, you probably want to .join("") at the end of the .map – Cal Irvine Feb 03 '20 at 20:45
  • https://codeburst.io/javascript-map-vs-foreach-f38111822c0f I find this article is pretty good at explaining the different uses. – Cal Irvine Feb 03 '20 at 20:50
0

If you just want to manipulate a string you might want to use the replace function

const newString = str.toLowerCase().replace(/[a,e,i,o,u]/g, letter => letter.toUpperCase())

This first puts everything to lower case, and afterwards replaces all vowels (matching the regular expression) by their upper case versions.

Michael
  • 878
  • 5
  • 17