Erikamyself
Erikamyself

Reputation: 263

Javascript recursions. Why the following code works with .unshift() instead of .push()?

My brain believes that I should use .push() instead of .unshift() but freeCodeCamp and my console tell that this is the right way of doing it. I just don't understand how come my numbers go from 10 to 20 using .unshift(), and 20 to 10 using .push();

The way I read the code: if startNum is bigger than endNum return an empty array. Otherwise, create a variable called arr and assign to it the current startNum increased by 1 each time the code runs and return it into the array.

What am I doing wrong?

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

console.log(rangeOfNumbers(10, 20));

The console: (11) [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Upvotes: 0

Views: 149

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50807

One way to think of it is to imagine that the recursive call already worked properly. So rangeOfNumbers(11, 20) would yield [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]. And so const arr = rangeOfNumbers(startNum + 1, endNum) means that arr is [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]. Now you have startNum and arr and need to combine them. push would add startNum to the end. unshift properly adds it to the beginning.

But while we're here, I'd like to suggest a more elegant way to express that same algorithm:

const rangeOfNumbers = (start, end) => 
  start > end 
    ? []
    : [start, ... rangeOfNumbers (start + 1, end)]

Instead of if-else statements we have a single conditional expression. And we don't mutate a variable like arr in the process. I think it also more cleanly expresses the algorithm. Of course tastes may vary, and, if you're just learning JS, this may involve syntax you haven't seen yet. But if you do understand it, you might agree with me about its elegance.

Upvotes: 1

Snow
Snow

Reputation: 4097

unshift inserts an element into the beginning of the array.

Since you're iterating from the startNum to the endNum, consider the next to last recursive call:

const arr = rangeOfNumbers(startNum + 1, endNum);
arr.unshift(startNum);
return arr;

where startNum is 19 and endNum is 20. The recursive call returns an array with one element: [20]. Then you need to insert the 19 element in the proper position.

To do this, you'll need to insert the 19 at the beginning, to get:

[19, 20]

So, insert 19 at the beginning with unshift.

If you used push instead, from the original [20], you'd get:

[20, 19] // 19 added to end

and then

[20, 19, 18] // 18 added to end

and so on, which isn't in the right order.

You could use push if you inserted elements before the recursive call.

function rangeOfNumbers(startNum, endNum, arr = []) {
  arr.push(startNum);
  if (startNum < endNum) {
    rangeOfNumbers(startNum + 1, endNum, arr);
  }
  return arr;
}

console.log(rangeOfNumbers(10, 20));

Upvotes: 1

Related Questions