Basic JavaScript - Use Recursion to Create a Range of Numbers

Can someone help me figure out why I need to use “unshift” instead of “push”? Isn’t the first value that is pushed to the array 5? And if I use “push,” shouldn’t the value after that be on the right side, resulting in an overall return of [5, 6, 7, 8]? Why is it reversed, and why do I have to change it to “unshift”? I’m quite confused.

Your code so far

function rangeOfNumbers(startNum, endNum) {
  if (startNum > endNum){
    return [];
  }else{
    const numberArray = rangeOfNumbers(startNum + 1, endNum);
    numberArray.unshift(startNum);
    return numberArray;
  }
};

console.log(rangeOfNumbers(5, 8));

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36

Challenge: Basic JavaScript - Use Recursion to Create a Range of Numbers

Link to the challenge:

It is evaluated from the last call to the first, backwards, so if you use push you will end up with the numbers in the opposite direction to what you were expecting:

Take:

rangeOfNumbers(1, 3);

Inside the function, you are going to set the value of the variable numberArray, and then return it. How many times rangeOfNumbers gets called is important. It’s been called once so far. Then:

// 1 is not greater than 3, so go to `else`
const numberArray = rangeOfNumbers(2, 3);

rangeOfNumbers has been called twice, like rangeOfNumbers1(rangeOfNumbers2).

numberArray is not a concrete value yet, it’s a function call.

// 2 is not greater than 3, so go to `else`
const numberArray = rangeOfNumbers(3, 3);

rangeOfNumbers has been called three times, like rangeOfNumbers1(rangeOfNumbers2(rangeOfNumbers3)).

numberArray is not a concrete value yet, it’s a function call.

// 4 IS greater than 3
const numberArray = rangeOfNumbers(4, 3);

Now, when we increment the first argument by one, we get rangeOfNumbers(4, 3). This returns an actual value: we don’t go to the else, we do not call rangeOfNumbers, we return a value, []. And now that rangeOfNumbers is actually returning values, go back up that chain of nested functions, from the innermost call to the outermost.

rangeOfNumbers(1, 3)
  rangeOfNumbers(2, 3)
    rangeOfNumbers(3, 3)
      []

Innermost call: numberArray equals [], next line says unshift startNum, which is 3.
Move back a level, numberArray equals [3], next line says unshift startNum, which is 2.
Move back a level, numberArray equals [2, 3], next line says unshift startNum, which is 1.
Move back a level, we’re back at the start, return numberArray, which is now [1, 2, 3].


If it had been push instead:

  1. Innermost call: numberArray equals [], next line says push startNum, which is 3.
  2. Move back a level, numberArray equals [3], next line says push startNum, which is 2.
  3. Move back a level, numberArray equals [3, 2], next line says push startNum, which is 1.
  4. Move back a level, we’re back at the start, return numberArray, which is now [3, 2, 1].


(closest comparison I could think of without thinking about it too much – can probably get a direct analogy using a do/while loop, but this should do):

function rangeOfNumbers(start, end) {
  let numberArray = [];
  for (let i = end; i >= start; i--) {
    numberArray.unshift(i);
  }
  return numberArray;
}
  1. rangeOfNumbers(1, 3)
  2. numberArray is []
  3. i is 3, that is greater than or equal to 1, numberArray is [3]
  4. i is 2, that is greater than or equal to 1, numberArray is [2, 3]
  5. i is 1, that is greater than or equal to 1, numberArray is [1, 2, 3]
  6. i is 0, that is NOT greater than or equal to 1, loop ends.
  7. return [1, 2, 3 ]

Also, just for comparison another way to do it recursively which doesn’t mutate the array, and is basically a same as a loop (mutating IMO confuses things, though it is I guess more efficient):

function rangeOfNumbers(start, end, numArr = []) {
  if (start > end) {
    return numArr;
  } else {
    return rangeOfNumbers(start + 1, end, numArr.concat(end))
  }
}

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.