1

Hello I'm trying to understand recursion in JavaScript.

So far I have:

function countVowels(string) {
    let vowelCount = 0;

    // if we're not at the end of the string,
    // and if the character in the string is a vowel

    if (string.length - 1 >= 0 && charAt(string.length -1) === "aeiouAEIOU") {

    //increase vowel count every time we iterate 

        countVowels(vowelCount++);
    }
    return vowelCount;
}

First of all, this is giving me issues because charAt is not defined. How else can I say "the character at the current index" while iterating?

I can't use a for-loop - I have to use recursion.

Second of all, am I using recursion correctly here?

countVowels(vowelCount++);

I'm trying to increase the vowel count every time the function is called.

Thanks for your guidance.

0

4 Answers 4

3

If you're interested, here is a version that does not keep track of the index or count, which might illuminate more about how the recursion can be done.

function countVowels(string) {
  if (!string.length) return 0;
  return (
"aeiou".includes(string.charAt(0).toLowerCase()) +
countVowels(string.substr(1))
  );
}

console.log(countVowels("")); // 0
console.log(countVowels("abcde")); // 2
console.log(countVowels("eee")); // 3

// Note that:

console.log('"hello".substr(1)', "hello".substr(1)) // ello
console.log('"hello".charAt(0)', "hello".charAt(0)) // h
console.log('"aeiou".includes("a")', "aeiou".includes("a")) // true
console.log('"a".includes("aeiou")', "a".includes("aeiou")) // false

Our base case is that the string is empty, so we return 0.

Otherwise, we check if the first character in the string is a vowel (true == 1 and false == 0 in javascript) and sum that with counting the next (smaller by one) string.

Sign up to request clarification or add additional context in comments.

4 Comments

Sorry but I'm frustrated with trying to learn this. I would expect the syntax of checking whether or not there's a vowel in the string to be string[i].includes("aeiou".toLowerCase()). Don't understand why it's "aeiou".includes(etc) but okay. Then you have (string.charAt(0).toLowerCase()) - won't this only check the first character in the string? I don't see how iteration through the string is occurring? Lastly I just looked up the .substr() method and found that this will extract a part of the string. So in that case I would expect it to extract "b" from "abcde"?
@HappyHands31 We need to only check first character because everytime we are removing the first character and sending the rest to the function countVowels(string.substr(1))
@MaheerAli Oh so string.substr(1) is what's removing the first character every time?
@HappyHands31 I have added a couple lines to the snippet so you can see those items in action separately. Try playing in the dev console or a snippet to see how it works.
1

You are making two mistakes:

  • You should have three parameters string , count(count of vowels) and current index i.
  • You should use includes() instead of comparing character with "aeiouAEIOU"

function countVowels(string,count= 0,i=0) {
    if(!string[i]) return count
    if("aeiou".includes(string[i].toLowerCase())) count++;
    return countVowels(string,count,i+1);
}
console.log(countVowels("abcde")) //2

As asked by OP in comments "Can you please explain why it'sif("aeiou".includes(string[i].toLowerCase())) instead of if(string[i].includes("aeiou".toLowerCase()))"

So first we should know what includes does. includes() checks for string if it includes a certain substring passed to it or not. The string on which the method will be used it will be larger string and the value passed to includes() be smaller one.

Wrong one.

"a".includes('aeiou') //checking if 'aeiou' is present in string "a"   //false

Correct one.

"aeiou".includes('a') //checking if 'a' is present in string "aeiou"  //true

3 Comments

Can you please explain why it's if("aeiou".includes(string[i].toLowerCase())) instead of if (string[i].includes("aeiou".toLowerCase())) - doesn't .includes() happen to an existing value? Like if string.includes("dog")
string[i] is the character through which we are iterating. And always short string is included by large one. Here small one is string[i] and large one is "aeiou".
1

One possible solution would be:

function countVowels(string, number) {
  if (!string) return number;
  return countVowels(string.slice(1), 'aeiouAEIOU'.includes(string[0])? number + 1 : number);
}

// tests
console.log('abc  --> ' +  countVowels('abc', 0));
console.log('noor --> ' + countVowels('noor', 0));
console.log('hi   --> ' + countVowels('hi', 0));
console.log('xyz  --> ' + countVowels('xyz', 0));

and you should call your function like: countVowels('abc', 0)

Notes about your solution:

  1. you always reset vowelCount inside your function, this usually does not work with recursion.
  2. you defined your function to accept a string, but recall it with an integer in countVowels(vowelCount++); this it will misbehave.
  3. always remember that you have to define your base case first thing in your recursion function, to make sure that you will stop sometime and not generate an infinite loop.

Comments

0

Alternative ES6 solution using regex and slice() method. Regex test() method will return true for vowels and as stated in a previous answer JavaScript considers true + true === 2.

const countVowels = str => {
  return !str.length ? 0 : /[aeiou]/i.test(str[0]) + countVowels(str.slice(1));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.