I'm trying to write a recursion that will create a countdown array. The function should take an array in the myArray parameter and append the numbers n through 1 based on the n parameter. For example, calling this function with n = 5 will pad the array with the numbers [5, 4, 3, 2, 1] inside of it. Your function must use recursion by calling itself and must not use loops of any kind.
Seems to be multiple ways to write a recursion, is there a generally accepted and easily readable method?
function countdown(myArray, n){
if (n>=1) {
myArray = countdown(myArray, n-1);
myArray.unshift(n);
}
return myArray;
}
function countdown(myArray, n){
if (n<=0) {
return;
} else {
myArray.push(n);
countdown(myArray,n-1);
}
}
If I enter countdown(myArray, 5), both functions returns an array called myArray = [5,4,3,2,1].
The bottom function has a typical base case... while the top function doesn't? I'm more comfortable writing it using the bottom method but I'm kind of confused why it works. Wouldn't bottom function be calling until it gets to countdown(myArray,0), then return and start going back up the stack. So wouldn't it start with myArray.push(1) before it works its way back up the stack causing the answer to be [1,2,3,4,5] instead of [5,4,3,2,1]?
If you add an else branch into the first function, and move the return into both branches (thus not changing the meaning):
if (n>=1) {
myArray = countdown(myArray, n-1);
myArray.unshift(n);
return myArray;
} else {
return myArray;
}
Now invert the if statement (swapping both the condition and the branches):
if(n <= 0) {
return myArray;
} else {
myArray = countdown(myArray, n-1);
myArray.unshift(n);
return myArray;
}
So as you can see, both functions are equal, as they can be transformed i to each other without making breaking changes (however one does return myArray while the other one does not).
Now wheres the base case in the first function? Well, if n is 0 or less, it does not enter the if and as the recursive call is inside the ifs branch ... it does not call itself again.
Related
function twoSum(numbers, target) {
var result = [];
numbers.forEach(function(value, index) {
return numbers.forEach(function(value2, index2) {
if (value + value2 === target) {
result.push(index, index2);
return result;
}
})
})
return result;
}
twoSum([1, 2, 3], 4);
//Output - [ 0, 2, 1, 1, 2, 0 ]
Hi - I'm working on a particular codewars problem and I seem to be misunderstanding the usage of return for callback functions. In this particular problem I just want to find the first two sums of numbers that equal the target and push those index values into result. I don't want to keep iterating through my function after that - meaning I only want the first pair that's found. My current output gives me all the index values for the target sum. Not just the first 2. It seems I am not using my return commands correctly. My current line of thought is that return result returns a value to my nested callback of parameters (value2, index2). That result is then returned to my outside function of (value,index). Why does my loop not cease after that return?
It doesn't end because .forEach cannot be terminated early. forEach is not paying any attention to the values you return. If you want to terminate early you'll need to use a different approach.
If you want to stick with array methods, there are .some and .every. The former continues until a run of your function returns true, and the latter continues until a run of your function returns false. These are meant for doing compound OR's and compound AND's with every element of the array, but they can kinda be used for your case too.
numbers.some(function(value, index) {
return numbers.some(function(value2, index2) {
if (value + value2 === target) {
result.push(index, index2);
return true;
}
return false;
})
})
Or you could use a standard for loop, with the break keyword when you want to stop the loop.
Beside the not working return statement for a outer function, you need to take a different approach which uses only a single loop and an object for storing the index of the found value.
function twoSum(numbers, target) {
var indices = {};
for (let i = 0; i < numbers.length; i++) {
const number = numbers[i];
if (number in indices) return [indices[number], i];
indices[target - number] = i;
}
}
console.log(twoSum([1, 2, 3], 4));
I'm trying to use Closure in JS in order to declare a function named **expandArray()** which contain an Array named **myArray**and Returns an anonymous function that directly modifies myArray by increase the values by 1 than the returned function then returns the value of **myArray**. My Problem here one the last part where the returned function return a function not Array value ?!
This is my code
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray());
As its closure, you have invoked it only once like expandArray() , which return the function itself, which is below
ƒ () {
myArray.map( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
}
you need to invoke it again to get your result back as below
expandArray()() //[2, 2, 2]
Ref: How do JavaScript closures work?
You've written a function that returns a function when you run it:
function expandArray() {
const myArray = [...];
// return this when we run expandArray():
return function() {
...
}
}
So if you run expandArray(), it is going to return your anonymous function. Exactly as you wrote it to do.
If you then want to get an actual reference to that internal myArray, you'll now need to actually run that returned function, so:
var getMyArray = expandArray();
var result = getMyArray();
console.log(result);
Just fyi, you are doing something very similar to the memoization pattern.
To address your problem: as everyone else has already said, you return a function from expandArray. What you want is to return the closed array (after incrementing every element).
To do this, you can use something called immediately-invoked function expression in combination with arrow functions to simplify your code:
const expandArray = (() => {
const myArray = [1, 1, 1];
return () => {
myArray.forEach((num, index) => {
myArray[index] = num + 1;
});
return myArray;
};
})();
console.log(expandArray());
console.log(expandArray());
console.log(expandArray());
There are a couple of things incorrect with your code.
you can't change the values of variables declared within const. In the case of Objects and Arrays, you aren't allowed to assign a new reference with a new Array or Object. We change the declarative operator to let instead of const.
myArray.map doesn't mutate myArray, it returns a new array based on the input from myArray and your passed in function that adds 1 to each value. We can fix this by assigning myArray.map to the already declared myArray. That is to say, we're overwriting the old Array with a new one. This is why const in the above bullet point won't work.
Your map function parameters are unnecessary The parameters for it that are most often used are the first two available, which is the item in the array and the index of that item. Since we're iterating over each number using map the function can simply return the item (declared as num in your code) plus 1. This will return a new array with your changed values. So we don't need the index at all..
When you return a function from a function you need to invoke both to get the second return value. When using a closure you need to keep a reference to the initial returned function. This is confusing but if you think of it as levels - in your expandArray function you have two levels. The function itself and the function you're returning. when you call expandArray() you're invoking the first level, and making the second level available to be invoked, this is why expandArray() returns the second function and expandArray()() will return the value from the second function. We save the returned function in a variable called add_to_array by setting it equal to expandArray(), and then we consistently invoke add_to_array to return the new Array with the changed values.
This is the most confusing part of closures, but what is happening is that the add_to_array variable is like a wedge in the function. It stops myArray from being deleted by the Browser because it requires the function to exist in the event that it needs to be invoked again. It's kind of like a bookmark in a book. For the story to make sense whenever you open it, you don't just tear out the pages before the bookmark. You keep the story intact because in five years when you come back to it you may need to read the previous pages at the bookmark to remember where you were. A closure works the same way. It can't remove the variables from the initial expandArray function call because add_to_array is a placeholder in the middle of it. The reference point keeps the book open.
(for more info on closures you can check out this article here Destroying Buildings - A Guide to JavaScript Closures)
function expandArray() {
let myArray = [1, 1, 1];
return function () {
myArray = myArray.map( function (num) {
return num + 1;
});
return myArray;
};
}
let add_to_array = expandArray();
console.log( add_to_array(),add_to_array(),add_to_array() );
In your original code, you're only getting the return value of expandArray(), which is the function you're trying to use as a closure. In order to get the closure's return value, try this out:
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray()());
The second set of parentheses after the call to expandArray() will invoke the closure and return the values you're seeking.
Old post, but I still like to contribute. I came up with this solution, as I think you want add something to the array instead of incrementing the numbers.
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1)
return myArray
}
}
const array = expandArray();
const result = array();
console.log(result)
3years after this question was posted this lines of code works fine for me
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1);
return myArray;
};
}
let newArray = expandArray();
console.log(newArray());
Note this is my first contribution on stack overflow.
This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 5 years ago.
First time posting. Sorry for bad formatting. I am trying to get my function to work. The current issue is that the recursion stops as soon as the recursive function is called for the first array element. I need it to keep going even after an array is called.
TLDR: I want to flatten the array.
function steamrollArray(arr) {
var newArr=[];
//return Array.isArray(arr[2]);
//takes an array of which some elements will also be arrays and pushes its non-array elements to a new array (newArr)
function recurseArr(a){
for (i=0; i<a.length; i++){
//recursion where you take the array element (also an array) and apply the same function until you get an element
if(Array.isArray(a[i])){
//&& i==a.length
recurseArr(a[i]);
}
//case where the original array element is not an array but an element already
else{
newArr.push(a[i]);
}
}
}
//end of recurseArr
recurseArr(arr);
return newArr;
}
steamrollArray([1, 2, [2, 3], 2, [[[4]]]]);
desired output: [1,2,2,3,2,4]
You have two problems.
You're mixing two styles of output. On the one hand, it looks like your functions return values. But on the other hand, it looks like the final output is supposed to come from newArr. In fact, the code is written mostly correctly, but you need to stick with the newArr paradigm and stop trying to return from the inner functions.
Fix that like this:
if(Array.isArray(a[i])){
//&& i==a.length
recurseArr(a[i]); // get rid of `return`
}
and this:
return newArr; // remove this
and this:
// return recurseArr(arr); // don't do this
recurseArr(arr);
return newArr;
You don't declare your counter variable i with var or let. This means it doesn't have function scope but is actually a member of the global scope, such as window in a browser or something else in Node, and thus you're modifying the same exact instance of i in each loop (as if you had declared var i before the outer function).
Making both these changes now yields (comments removed for easier understanding):
function steamrollArray(arr) {
let newArr = [];
function recurseArr(a) {
for (let i = 0; i < a.length; i += 1) {
if (Array.isArray(a[i])) {
recurseArr(a[i]);
}
else {
newArr.push(a[i]);
}
}
}
recurseArr(arr);
return newArr;
}
Which works perfectly.
The main problem is with the return statement inside of your loop. The return statement exits your for loop.
If your main intent is to flatten the array, you are better off using a utility library like lodash or ramda, where flattening is just a:
R.flatten([1, 2, [2, 3], 2, [[[4]]]])
I hope this is not a repeated question-- though I couldn't find much help on this.
I am practicing recursive functions (I'm a newbie), and I'm trying to multiply each number in an array. Sort of like a factorial. I have this code, but it is only returning undefined as a result.
Here is the code:
var stack = [];
function countDown(int) {
stack.push(int);
if (int === 1) {
return 1;
}
return countDown(int - 1);
}
function multiplyEach() {
// Remove the last value of the stack
// and assign it to the variable int
int = stack.pop();
x = stack.length;
// Base case
if ( x === 0 ) {
return;
}
// Recursive case
else {
stack[int - 1] = int * stack[x - 1];
return multiplyEach(int);
}
}
// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
Thank you so much for any insight.
Cheers!
The first thing to address is that your multiplyEach() function should have a parameter named int, from the looks of it. The approach you're using might be better suited to a different technique, but we'll get to that.
Next, in multiplyEach(), there are two possible paths:
The stack still has elements, in which case we multiply the new top value on the stack by the old one and move on to another run of multiplyEach.
The stack is empty, and we just return.
The problem here is that we aren't actually returning the final stack value, or leaving it on there to access later. We've effectively lost it, so what is the function outputting?
In many languages, we would have defined a return type for this function, either void for no value, or int for returning the multiplied value. However, in Javascript, there is no such thing as a function that doesn't return a value; "nothing" in JS is represented as undefined. When you return multiplyEach(), you're pushing another call of it onto the call stack, and waiting for an actual return value... which ends up being return;, which JS interprets as return undefined;. Again, in most languages, there would be some form of error, but not in JS! Let's look at two possible implementations:
The custom stack you use:
// your stack is fine, so we'll skip to the meat
function multiplyEach() {
var int = stack.pop(), x = stack.length;
stack[x - 1] *= int;
if(x < 2) // to multiply, we need at least two numbers left
return;
multiplyEach();
}
//...
multiplyEach();
console.log(stack[0]);
With a parameter, and using a list:
function multiplyEach(index) {
var int = list[index];
if(index == 0)
return int;
return int * multiplyEach(index - 1);
}
//...
console.log(multiplyEach(list.length - 1));
They're both different ways of implementing this recursively; all recursion inherently requires is for a function to call itself. Another possibility would have been having a parameter store the total, instead of multiplying the return values like in option 2; that's called tail recursion.
EDIT: noticed the base case for option 1 was in the wrong place, so I moved it. It should work now.
Recursively you can do this way:
function multiplyEach(arr, size) {
return size === 0 ? arr[size] : arr[size] * multiplyEach(arr, size - 1);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(multiplyEach(array, array.length - 1));
But you can do it using the native method reduce, then you could do simply this:
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(function(a, b) { return a * b; }));
ES6 version:
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce((a, b) => a * b));
I hope it helps.
There are times recursion is better suited to solve a problem and there are times iteration is better suited to solve a problem.
Recursion is better suited for performing an action until a condition is met then exiting, similar to a while loop.
Iteration is better suited for performing an action N number of times then exiting, similar to a for loop.
In our case, we want to input an array and output the product of all elements of that array. In other word, we want to perform N - 1 multiplications where N is the number of elements in the array. Since we know the number of operations we want to perform we should solve our problem with iteration which is done below.
var arr = [1, 2, 3]
var result = multiplyEach(arr)
console.log(result)
// -> 6
function multiplyEach(arr) {
var result = 1
arr.map(function(value) {
result *= value
})
return result
}
Keep in mind though that the above is an approximate rule of thumb because sometimes recursion will be a more elegant solution than iteration. Here's the simple, recursive, and elegant implementation of the real factorial.
function factorial(value) {
return 1 === value ? 1 : value * factorial(value - 1)
}
The iterative implementation of factorial is not as pretty in while loop form nor for loop form.
function factorial(value) {
var result = 1
while (value > 0) {
result *= value
value--
}
return result
}
function factorial(value) {
var result = 1
for (var i = 0; i < value; i++) {
result *= value
}
return result
}
I think the main issue is that you do not have an argument in the multiplyEach() definition, but you attempt to call it with one inside the function.
Something like this works:
var stack = [1, 2, 3, 4, 5, 6, 7];
function multiplyEach(arr) {
if (arr.length == 0) {
return 1;
} else {
return arr.pop() * multiplyEach(arr);
}
}
console.log(multiplyEach(stack));
The base case in the recursive function multiplyEach() returns undefined.
That's where your problem lies.
A simple fix would be:
var stack = [];
var multipliedStack = [];
function countDown(int) {
stack.push(int);
if (int === 1) {
return 1;
}
return countDown(int - 1);
}
function multiplyEach() {
// Remove the last value of the stack
// and assign it to the variable int
int = stack.pop();
x = stack.length;
// Base case
if ( x === 0 ) {
return multipliedStack.reverse();
}
// Recursive case
else {
multipliedStack.push(int * stack[x - 1]);
return multiplyEach(int);
}
}
// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
I don't fully get what you mean by "sort of like a factorial"? What exactly is the function supposed to do?
To understand recursion you need to wrap your head around what a recursive base case is and also I think you need to revise push() and pop() which are not used in a proper way in your code.
Recursive functions are usually abit confusing if you are used to iteration, keep trying and you'll get comfortable with it rather quick.
Array.reduce() takes an array and combines elements from the array with an accumulator until all the elements are consumed.
Is there a function (often called "unfold" in other languages) that starts with a value and keeps generating elements until a complete array is produced (the accumulator is depleted)?
I am trying to do this as part of converting between arbitrary bases. The code as I have it is as follows, but I would like to eliminate the raw loop.
var dstAlphabet = "0123456789ABCDEFGH";
var dstBase = dstAlphabet.length;
var wet = BigInteger(100308923948716816384684613592839);
var digits_reversed = [];
while (wet.isPositive())
{
// var digitVal = wet % dstBase
var divRem = wet.divRem(dstBase); // [result of division, remainder]
wet = divRem[0];
digits_reversed.push(dstAlphabet.charAt(divRem[1].toJSValue()));
}
return digits_reversed.reverse().join("");
// These days you can do it in one line:
const unfold = (accumulator, length) => length <= 0 ? accumulator : unfold([length, ...accumulator], length -1)
// invoke it like this:
const results = unfold([], 5)
// expected results: 1,2,3,4,5
console.log(results.join(','))
Since we're looking for a concise way to generate a given number of elements as an array, this "unfold" function does it with recursion.
The first argument is the accumulator array. This needs to be passed along, and eventually is returned when it holds the entire collection. The second argument is the limiter. This is what you use to dimension your resulting array.
In each call, we first test if the base case is reached. If so, the answer is easy: just return the given array. For the general case, we are again unfolding, but with a smaller value, so we prepend one value to accumulator, and decrement length.
Since we're using the spread operator and a 'computed-if' the function is concise. Using the arrow style also lets us avoid the 'function' and 'return' keywords, as well as curly-braces. So the whole thing is a one-liner.
I basically use this technique as a for-loop substitute for React JSX, where everything needs to be an expression (Array.map()).
The opposite of Array#reduce in Javascript is Array.from (or alternatively spread syntax). You can use it with any iterable object to generate an array:
array = Array.from(iterator); // same as array = [...iterator];
You can create an iterator by calling a generator function:
iterator = generate(params);
Generator functions use the special keyword yield to return their results (or yield* to return all results from another iterable). And they are depleted once they return:
function* convertBase(wet, alphabet) {
const base = BigInt(alphabet.length);
wet = BigInt(wet);
while (wet > 0) {
const digitVal = Number(wet % base);
wet = wet / base;
yield alphabet.charAt(digitVal);
}
}
console.log(Array.from(convertBase(100308923948716816384684613592839, "0123456789ABCDEFGH")).reverse().join(""));
Alternatively you can implement the iterator yourself without a generator function:
console.log(Array.from({
wet: BigInt(100308923948716816384684613592839),
base: BigInt(18),
alphabet: "0123456789ABCDEFGH",
[Symbol.iterator]: function() {
return this;
},
next: function() {
if (this.wet > 0) {
const digitVal = Number(this.wet % this.base);
this.wet = this.wet / this.base;
return {value: this.alphabet.charAt(digitVal)};
} else {
return {done: true};
}
}
}).reverse().join(""));
tewathia's comment seems like the idiomatic way to do it, but I guess if you want to do it the hard way, you could just write your own recursive primitive, like:
function unreduce(accumulator, operation, stopPredicate, ret) {
return helper([accumulator, ret])[1]
function helper(vals) {
if (stopPredicate(vals[0])) return vals[1];
return helper(operation(vals[0], vals[1]));
}
}
Which you might want to modify a bit to preserve this for the callbacks.
I'm not sure how great that is. It's kind of awkward with the operation callback needing to update both the accumulator and return values. The outer function can't save operation from having to return a length-2 array.
array.map((..) => { return [ .. ]; }).flat(1);