Reputation: 461
I am trying to get the range of numbers using recursion. Can someone explain to me why it isn't working?
function range(x,y){
var results = [];
if(x === y){
return results;
}
return results.push(range(x + 1,y));
}
range(1,5);
Upvotes: 4
Views: 8877
Reputation: 952
Lots of clever solutions posted, but I think this is a use case for the plain old 'for loop'. It's easier to see what's happening, and it will be easier for new devs on your team. My example is inclusive (it will include the min value and the max value), and it has an optional step parameter which will default to 1 if not passed in.
function range(min, max, step = 1) {
let arr = []
for (let i = min; i <= max; i = i + step ) {
arr.push(i)
}
return arr
}
Upvotes: 0
Reputation: 11
function rangeOfNumbers(firstNum, lastNum) {
if (firstNum - lastNum === 0) {
return [lastNum];
} else {
let rangeArray = rangeOfNumbers(firstNum, lastNum - 1);
rangeArray.push(lastNum);
return rangeArray;
}
}
console.log(rangeOfNumbers(1, 5))
Upvotes: 0
Reputation: 149
function rangeOfNumbers(startNum, endNum) {
if (startNum>endNum){
return [];
}
else{
const range = rangeOfNumbers(startNum+1, endNum);
range.unshift(startNum);
return range;
}
};
//or more simple
function rangeOfNumbers(startNum, endNum) {
return endNum>=startNum?rangeOfNumbers(startNum,endNum-1).concat(endNum):[];
};
Upvotes: 0
Reputation: 525
Let's firstly try to answer your "why" question before we give a solution because none of these answers explain your "why" question.
When you return results.push(<any argument>)
the return value is the length of the array after the push. On the first call in your example, x does not equal y, so we are returning the call to push. You can think of it like this:
return array.push(<anything>)
is going to be the same as:
array.push(<anything>)
return array.length
Therefore, you will always return the number 1
from this because the length of the array when you push the function call to it is 1. The content of that array will be another array that's nested all the way to the n levels deep where n is the range, but it's length will still be one and you will never see the content of this array unless you did it this way:
results.push(rangeOfNumbers(x+1, y))
return results;
In your example rangeOfNumbers(1, 5)
, if you logged that return value it would look like this:
[ [ [ [ [ ] ] ] ] ]
I solved it this way, but I like the functional solution that was posted by another user more:
function rangeOfNumbers(s, e) {
return s == e ? [s] : [s, ...rangeOfNumbers(s+1, e)];
}
Upvotes: 1
Reputation: 343
Try this:
function rangeOfNumbers(startNum, endNum) {
if (startNum - endNum === 0) {
return [startNum];
} else {
const numbers = rangeOfNumbers(startNum + 1, endNum);
numbers.unshift(startNum);
return numbers;
}
};
Upvotes: 5
Reputation: 31
Solution: Solved this recursion problem, which is taking 2 numbers as input and returning back the array which contains range of the numbers inclusive of the startNumber and EndNumber
Assumption-> end_num is always greater than start_num
function rangeOfNumbers(start_num, end_num) {
if(start_num!==end_num){
let numbers = rangeOfNumbers(start_num+1,end_num);
numbers.unshift(start_num);
return numbers;
}
else
return [start_num];
};
Upvotes: 2
Reputation:
The beauty of recursion is that you don't need local variables (var results
). You just pass state as arguments to each recursive iteration:
const concat = (xs, y) => xs.concat(y);
const range = (x, y) => {
const rec = (x, y, acc) => x < y ? rec(x + 1, y, concat(acc, x)) : acc;
return rec(x, y, []);
}
ES5 version in case you aren't familiar with the arrow syntax:
function concat(xs, y) {
return xs.concat(y);
}
function range(x, y) {
function rec(x, y, acc) {
return x < y ? rec(x + 1, y, concat(acc, x)) : acc;
}
return rec(x, y, []);
}
That isn't the most elegant solution though!
With recursion we can simply build up the stack with each recursive call. Each stack frame contains a computed partial result. Then we just need to unwind the stack and attach each partial result to an array:
const range = (x, y) => x < y ? [x].concat(range(x + 1, y)) : [];
Or more functional:
const concat = (xs, y) => xs.concat(y);
const range = (x, y) => x < y ? concat([x], range(x + 1, y)) : [];
Note that concat([x], range(x + 1, y))
is the recursive case and []
the base case.
Upvotes: 6
Reputation: 2031
Results will be always empty since you actually don't put anything in it.
What would work is this
function range(x,y){
var results = [];
if(x === y){
return results;
}
results.push(x);
return results.concat(range(x + 1,y));
}
range(1,5);
Upvotes: 1