Related
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.push(n);
return countArray;
}
}
console.log(countup(5));
After running the above code it returns an array: [1, 2, 3, 4, 5], but push() adds new values at the end of an array so when value of n was 5 it should push 5 to the end of the array and when value of n got 4 it should push 4 at the end of the array like [5,4].
So why not it is returning [5,4,3,2,1] ? It is hard to understand what is happening in this code probably because of this recursion. Isn’t unshift() (which add new values to start of the array) should return [1,2,3,4,5] and push() [5,4,3,2,1] why opposite is happening?
As #Joseph stated in a comment the second to last function call would get pushed to the array first, then it would return that array, where it immediately adds the next number up the call stack.
Here are the steps being taken.
Initial call enters itself recursively n times, where the bottom call returns [] and then [1], [1, 2] ... [1, 2, ..., n] all the way up the call stack where upon the first function call ends and the program does something else.
To get [n, ..., 2, 1] you need to use the Array.prototype.unshift() method, which takes any javascript primitive type, ie String, Number, Boolean, and Symbols, in a comma separated format, like countArray.unshift(4, 5) or countArray.unshift(...anotherArray), and adds them to the beginning of the array.
ie
let someArr = [3, 2, 1];
someArr.unshift(5, 4);
console.log(JSON.stringify(someArr));
// outputs [5, 4, 3, 2, 1]
or
let someArr = [1, 2, 3];
let anotherArr = [5, 4]
someArr.unshift(...anotherArr);
console.log(someArr);
// outputs [5, 4, 1, 2, 3]
Where the output of
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.unshift(n);
return countArray;
}
}
console.log(countup(5));
will be [5, 4, 3, 2, 1] tested with node in Vscode.
One useful way to think about this is to start by imagining you already had a function that does what you want for lower values, and then see how you would write one that works for higher values. That imaginary function should be a black box. All we should know is that it does what we want in the case of lower values. We don't care about its implementation details.
So lets say we had a function imaginaryBlackBox, and we knew that it returned the correct countUp values that we want. So, for instance, we know that imaginaryBlackBox (4) returns [1, 2, 3, 4].
Now, knowing that, how might we write a function that works for an input of 5 as well? How about something like this:
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = imaginaryBlackBox(n - 1);
countArray.push(n);
return countArray;
}
}
Again, we don't know how imaginaryBlackBox works. We just know that it returns the correct result for lower values of n. Our base case remains obvious. For another case, some n greater than 0, we call imaginaryBlackBox(n - 1), and by our basic assumption, we know that will return [1, 2, 3, ..., (n - 1)], which we store in countArray. Then we push n onto that array, to end up with [1, 2, 3, ..., (n - 1), n]. We return that value and we're done.
Now here's the trick. We know an implementation of imaginaryBlackBox -- it's the function we're writing! So we can simply replace it with countUp and know it will work.
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countUp(n - 1);
countArray.push(n);
return countArray;
}
}
This required a few assumptions, and they are important to all recursive functions:
There is at least one base case whose value we can calculate without any recursive call. Here, when n is < 1, we simply return [].
For other cases, we can break down our problem into one or more recursive cases, where the input is in some clear and measurable way closer to a base case, so that subsequent steps will hit a base case in a finite number of calls. Here we reduce n by 1 on every step, so eventually it will be below 1.
Our function is effectively pure: its outputs depend only on its inputs. That means we can't count on changing a global variable or reading from one that might be changed elsewhere. Note that I use the qualifier "effectively" here; it doesn't matter if this function has observable side-effects such as logging to the console, so long as its output is dependent only on its input.
Anytime you have those conditions, you have the makings of a good recursive function.
Say you have an array like this:
arrayExample = [1, 2, 3, 4, 5, 6, 7]
I want to use the map function to iterate through arrayExample and return true if all the numbers are less than 8, false if they are not. However, when I do this I get an array of trues (like: [true, true, true... etc])
Would I be able to return just 1 value?
Here is my code so far:
var testBoolean = true;
var array = [1,2,3,4,5,6,7];
testBoolean = array.map(m => {
//if a number in the array is >=8, changes the testBoolean to false and return false only
if(m >= 8)
{
return false;
}
//VS code said I had to have a return here, I believe its because I need to have in case m < 8 (edited after reading a comment)
return true;
})
//prints an array [true,true,true,true,true,true,true]
document.write(testBoolean);
I'm a bit new to "map" but I believe it does this since it returns a value for every element, just confused on how to make it so it returns 1 true or false.
The simplest solution is to use .some().
We don't need to check every value. We need to find the first value not less than 8.
const array = [1, 2, 3, 4, 5, 6, 7]
const testBoolean = !array.some(m => m >= 8)
console.log(testBoolean)
For something like this .map() isn't the right tool. .map() is for converting all the elements in your array to new elements (ie: mapping each element to a new transformed value). As a result, .map() will always return an array (unless this behaviour is intentionally modified). Instead, you can use .every() for this, which will tell you if all elements in your array match your condition (ie: if your function returns true for every element, then you'll get true as your result, otherwise you'll get false). The .every() method will terminate early as soon as it finds one element which your callback function returns false for, which can help with efficiency:
const array = [1, 2, 3, 4, 5, 6, 7];
const testBoolean = array.every(m => {
if (m >= 8) {
return false;
}
return true;
});
console.log(testBoolean);
This can be written more concisely, by just returning the result of m < 8 (this will either evaluate to true or false)
const array = [1,2,3,4,5,6,7];
const testBoolean = array.every(m => m < 8);
console.log(testBoolean);
From a more general perspective, if you want to return a single value from an Array, .reduce() is your friend.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
Specifically in your case, you could do
array.reduce(function(accumulator, currentVal, i, arr) {
return accumulator && currentVal < 8;
}, true));
So .reduce() iterates through your array with an initial value true and returns the "previous" value (accumulator) AND whether the current value is less than 8.
You could think of it as
(true && (a[0] < 8 && (a[1] < 8 ... )))
The returned value at each iteration becomes the accumulator of the next. In this way you could not only do math operations but also change an array of a certain shape (e.g. array of {w:0, h:0} objects) to an output of another (e.g. a single number being the sum of all the hypotenuses calculated from each w and h).
I am supposed to rotate an array of integers clockwise in JS.
Here is my code for it:
function rotateArray(N, NArray)
{
//write your Logic here:
for(j=0;j<2;j++){
var temp=NArray[N-1];
for(i=0;i<N-1;i++){
NArray[i+1]=NArray[i];
}
NArray[0]=temp;
}
return NArray;
}
// INPUT [uncomment & modify if required]
var N = gets();
var NArray = new Array(N);
var temp = gets();
NArray = temp.split(' ').map(function(item) { return parseInt(item, 10);});
// OUTPUT [uncomment & modify if required]
console.log(rotateArray(N, NArray));
The code accepts an integer N which is the length of the array. The input is as follows:
4
1 2 3 4
The correct answer for this case is supposed to be
4 1 2 3
But my code returns
4 1 1 1
I cannot find where my code is going wrong. Please help me out.
All you need to do is move one item from the end of the array to the beginning. This is very simple to accomplish with .pop() (removes an item from the end of an array), then declare a new array with that element as the first:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem, ...NArray];
}
console.log(rotateArray(1, [1, 2, 3, 4]));
Doing anything else, like using nested loops, will make things more unnecessarily complicated (and buggy) than they need to be.
If you don't want to use spread syntax, you can use concat instead, to join the lastItem with the NArray:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem].concat(NArray);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
If you aren't allowed to use .pop, then look up the last element of the array by accessing the array's [length - 1] property, and take all elements before the last element with .slice (which creates a sub portion of the array from two indicies - here, from indicies 0 to the next-to-last element):
function rotateArray(N, NArray) {
const lastItem = NArray[NArray.length - 1];
const firstItems = NArray.slice(0, NArray.length - 1);
return [lastItem].concat(firstItems);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
function rotate(array,n){
Math.abs(n)>array.length?n=n%array.length:n;
if(n<0){
n=Math.abs(n)
return array.slice(n,array.length).concat(array.slice(0,n));
}else{
return array.slice(n-1,array.length).concat(array.slice(0,n-1));
}
}
console.log(rotate([1, 2, 3, 4, 5],-3));
The answer by #CertainPerformance is great but there's a simpler way to achieve this. Just combine pop with unshift.
let a = [1,2,3,4];
a?.length && a.unshift(a.pop());
console.log(a);
You need to check the length first so you don't end up with [undefined] if you start with an empty array.
I've been reading a lot about recursive functions recently though I wasn't able to figure this one out until today. I think I now understand recursion better. Hopefully I can help someone else who is still struggeling with it:
function count(n) {
if (n === 1) {
return [1];
} else {
var numbers = count(n - 1);
numbers.push(n);
return numbers;
}
}
console.log(count(3));
The result of count(3) will be: [1, 2, 3]
We pass in 3 into count(n). Since n is not equal to 1 we go straight to the else statement. numbers = count(3 - n) or numbers = count(2) if we pass in n. What happens next is recursion:
Since we don't know what exactly count(2) is we have to run it to figure out. So we run count(2). n is not equal to 1 so we go to the else statement again. numbers = count(1). Recursion again. We put in 1 for n and this time the function returns [1].
Now since we know that count(1) = [1] we are able to solve count(2). count(2) is numbers = count(1) or numbers = [1]. This time we go ahead in our code and push in n numbers.push(n) which is 2. So count(2) returns [1, 2]. Now since we know the result for count(2) let's solve count(3). count(3) is numbers = count(2) or numbers = [1, 2] putting in our result. Now push gets activated and voila, our result for count(3) is [1, 2, 3].
I'm really new to JavaScript and I've been struggling with this code for a test to get into a coding bootcamp. I wonder if anyone had any help they could give?
function putInTheMiddle(array, item) {
for (i = 0; i < 20; i++) {
let Middle = Floor.Math(array / 2);
array.slice(Middle, 0, item);
}
console.log putInTheMiddle([1, 3], 2);
console.log putInTheMiddle([1, 2, 4, 5], 3);
}
I would like it to print out the arrays as [1, 2, 3] and [1, 2, 3, 4, 5] respectively.
You don't need the loop, that will insert the number 20 times.
The function to get the floor of a value is Math.floor(), not Floor.Math().
You need to divide the array's length by 2, not the array itself.
The function modifies the array in place, but if you want to be able to call console.log() when calling the function, it needs to return the array as well.
You need to use the splice() method to insert into the array. slice() just extracts part of the array without modifying.
You need to put parentheses around the argument to console.log(), and this needs to be outside the function definition.
function putInTheMiddle(array, item) {
let Middle = Math.floor(array.length / 2)
array.splice(Middle, 0, item);
return array;
}
console.log(putInTheMiddle([1, 3], 2));
console.log(putInTheMiddle([1, 2, 4, 5], 3));
Try Math.floor rather than Floor.Math:
const putInTheMiddle = (array, item) => {
let middleOfArray = Math.floor(array.length / 2);
array.splice(middleOfArray, 0, item);
return array;
}
console.log(putInTheMiddle([1, 3], 2));
console.log(putInTheMiddle([1, 2, 4, 5], 3));
Use Math.floor with array.length - also, console.log is a function, so call it with parentheses ():
function putInTheMiddle(array, item) {
array.splice(Math.floor(array.length / 2), 0, item);
return array;
}
console.log(putInTheMiddle([1, 3], 2));
console.log(putInTheMiddle([1, 2, 4, 5], 3));
.as-console-wrapper { max-height: 100% !important; top: auto; }
What the OP posted needed a few corrections which the following code reflects:
function putInTheMiddle(arr, item) {
let m = Math.floor((arr.length / 2));
arr.splice(m, 0, item);
return arr;
}
let arr = putInTheMiddle([1, 3], 2);
console.log(`[` + arr.join() + `]`);
let arr2 = putInTheMiddle([1, 2, 4, 5], 3);
console.log(`[` + arr2.join() + `]`);
The user-defined function needs to return the altered array in each case if console.log is to display the intended result. Note, Math is an object and floor is a method just as console is an object and log is a method. The methods require parentheses.
In order to determine the middle index of the array, you need to find its length, easily available since it is a property of the array. After dividing the length in two, you need to round the result to the nearest integer less than or equal to its value and Math.floor() will aid in this endeavor.
Instead of using the slice method, the code utilizes the Array object's splice method which fits the task at hand perfectly.
I concur with #Barmar that the OP does not need the for-loop.
Lastly, I use the Array object's join() method to join the elements into a string for easy display, which does not permanently affect the array.
Since, you are new to javascript i would like to answer this with simple methods.
//array is the array in which you want to insert.
//item is the value which you want to insert.
function putInMiddle(array, item){
let index = Math.floor(array.length/2);
//array.splice is a method which takes 3 arguments.
//argument 1 is the index where you want to make change.
//argument 2 is number of elements you want to remove starting from that index.
//argument 3 is the element that you want to insert at that index.
//In your case no element needs to be removed, hence argument 2 is 0.
array.splice(index,0,item);
return array;
}
//Then you can call the function in console.log if you just want to print the value.
console.log(putInMiddle(['1','2','4','5'],'3'));
//This will print ['1','2','3','4','5']
The above code works perfectly if you just want to add 1 element. But what if you want to add more than one element at a time. Relax, i have got you covered for that. Use the following:
function putInMiddle(array, itemArr){
let index = Math.floor(array.length/2);
let numItems = itemArr.length;
for(let i=0; i<numItems; i++){
array.splice(index,0,itemArr[i]);
index++;
}
return array;
}
console.log(putInMiddle(['1','2','6','7'],['3','4','5']));
//This will print ['1','2','3','4','5','6','7']
Hope this helps!