Related
Write a function squareWave(arr) that takes in the following array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], and starts replacing the numbers, one by one, with zeroes, until it reaches a multiple of 5. From that point onwards, start replacing the numbers with 1s, until you reach the next multiple of 5.
Then, from that point onwards, start replacing with 0s again, then 1s again,and so on until you reach the end of the array.
My code is not working Anybody can help me?
let input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
function squareWave(arr) {
let zeros = true;
let output = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 5) {
arr[i] = 0;
} else if (arr[i] !== 5) {
arr[i] = 1;
}
}
console.log(arr)
}
Output should be=[0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1]
You are not keeping track if the current entry should be a 0 or 1. Also, you are not using variables zeros and output
Instead of a boolean, you can keep a 0 or 1 in the variable zeros and flip the value when the mod of 5 equals zero.
if (arr[i] % 5 === 0) {
Then for every iteration write the value of zeros
let input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
function squareWave(arr) {
let zeros = 0;
let output = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 5 === 0) {
zeros = 1 - zeros
}
output[i] = zeros;
}
return output;
}
console.log(squareWave(input));
Or in short:
let input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
let res = input.map(i => Math.abs(Math.floor(i / 5) % 2))
console.log(res)
You can use Array's map function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
let control = 0;
const list = input.map(value => {
if (value % 5 === 0) {
control = control === 0 ? 1 : 0;
}
return control;
});
console.log(list);
As this is clearly a homework question, I won't give you the answer, but suggest your next steps. You actually almost have the idea of the answer, but you didn't actually implement it.
I'm assuming your current code output looks like [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, ...]
At the beginning of your code you have a boolean variable called zeros. What do you think this boolean is for, and why haven't you used it in your loop?
So your current code is outputting 1 when the value is a multiple of 5, but then it forgets immediately after. How might you fix that?
To replace an element in an array:
Use the indexOf() method to get the index of the element.
Use bracket notation to change the value of the element at the specific index.
The value of the array element will get updated in place.
const arr = ['a', 'b', 'c'];
const index = arr.indexOf('a'); // it will give you 0
if (index !== -1) {
arr[index] = 'z';
}
console.log(arr); // it will give you ['z', 'b', 'c']
Why does the remaining in original array = [1, 3, 5, 7, 9]
Since arr.splice(i, 1) = i is the target index and 1 is the number of item to be removed, i is increases to 10 respectively from i++ which short for i = i + 1, So why does it remove 5 index and remain 5 in the array ? that's what i know so far and i have struggled to read the docs but still have no idea to understand, please explain it for me
let arr = [1,2,3,4,5,6,7,8,9,10];
for(let i = 1; i < arr.length; i++) {
arr.splice(i, 1);
}
It is because the length of arr decreases everytime splice function runs.
Here is how the array changes.
[2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 6, 7, 8, 9, 10]
[2, 4, 6, 8, 9, 10]
[2, 4, 6, 8, 10]
So every loop, i increases and arr.length decreases by 1. so only 5 loops runs and the result is [2, 4, 6, 8, 10]
You're wondering why it's removing 1, 3, 5, 7, and 9, right?
Here's why. As the for loop iterates, i keeps increasing by one.
HOWEVER, by calling .splice, you are removing the first element of the array, so as a result, every other element moves down an index.
Let's play this out step by step for a few iterations of the for loop.
i = 0; arr.splice(0, 1) removes 1, so arr is [2, 3, 4, 5, 6, 7, 8, 9, 10]
i = 1; arr.splice(1, 1) removes 3, not 2, because now 3 is at index 1 of arr. Performing the splice leaves arr as [2, 4, 5, 6, 7, 8, 9, 10].
i = 2; arr.splice(2, 1) removes 5, because 5 is currently at index 2. As a result, arr becomes [2, 4, 6, 7, 8, 9, 10].
Is it clear now what's going on?
If your goal is to successively remove each element, one at a time, then instead of calling .splice(i, 1) in each iteration of the loop, you should call .splice(0, 1), since the value at index 0 changes each time you call .splice.
Remember, arrays are 0 based. Second, the length is changing each time it evaluates.
MDN links:
Splice
Map
So you may want to try
i =< length
Where length is determined and is set ahead of time and constant. You can try mapping the array to a new one, so the original array stays pure and unaffected by the splice.
You need to check the for loop end condition, i is not increasing to 10. Why? because i < arr.length.
So it will like this :
Iteration 1:
i=0; arr.length = 10; arr = [1,2,3,4,5,6,7,8,9,10]; ==> result [2,3,4,5,6,7,8,9,10];
Iteration 2:
i=1; arr.length = 9; arr = [2,3,4,5,6,7,8,9,10]; ==> result [2,4,5,6,7,8,9,10];
Iteration 3:
i=2; arr.length = 8; arr = [2,4,5,6,7,8,9,10]; ==> result [2,4,6,7,8,9,10];
.
.
.and so forth
i = 5 ==> arr.length: 5 ==> final result : [2, 4, 6, 8, 10]
So if you want to delete all items using splice:
let arr = [1,2,3,4,5,6,7,8,9,10];
while(arr.length > 0) {
arr.splice(0, 1);
}
I'm trying to have a forEach loop over an array, but only the last few entries.
I'd know how to do this in a for loop, that'd look a bit like this:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
/* This will loop over the last 3 entries */
for(var x = arr.length; x >= 7; x--){
console.log(arr[x]);
}
Would there be any way of achieving the same results in a forEach loop?
You can use slice() and reverse() methods and then forEach() loop on that new array.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.slice(-3).reverse().forEach(e => console.log(e))
This is how you do it with forEach loop:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.forEach((element, index) => {
if(index>7) console.log(arr[index]);
})
You could take a classic approach by taking the count of the last elements and use it as counter and an offset for the index.
Then loop with while by decrementing and checking the counter.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
last = 3,
offset = array.length - last;
while (last--) {
console.log(array[last + offset]);
}
I was testing out how splice works while iterating through an array, and don't understand why 0 stayed in the list?
var array = [2, 5, 9, 14, 0, 1, 3, 6, 7];
for (var i = 0; i < array.length; i++) {
if (array[i]%2 == 0) {
array.splice(i,1);
}
}
//0 % 2 == 0 is true, and yet
//array = [5, 9, 0, 1, 3, 7]
0 is getting skipped
You are mutating (changing) the array while you're iterating through it. This is a programming no-go.
Let's walk through...
i = 0 and 2 is even and gets spliced, your array is now [5, 9, 14, 0, 1, 3, 6, 7]
i = 1 and we didn't even check 5 which is in index 0 now... we're now checking 9 which is odd, fine
i = 2 and 14 is even and gets spliced, your array is now [5, 9, 0, 1, 3, 6, 7]
i = 3 and 0 gets skipped (as 0 is in index 2 now), 1 is odd, fine
i = 4 is odd fine
i = 5 is even and get spliced
i = 6 is odd fine
What you really want is this...
Array.prototype.filter = function(func) {
var result = new Array();
for (var i = 0; i < this.length; ++i)
if (func(this[i]))
result.push(this[i]);
return result;
}
values = [2, 5, 9, 14, 0, 1, 3, 6, 7];
odd_only = values.filter(function(x) { x % 2 != 0; });
Every time you remove a value from the array, you skip the one that follows it, because the array is reindexed on every splice. You can loop backwards instead:
var array = [2, 5, 9, 14, 0, 1, 3, 6, 7];
for (var i = array.length-1; i >= 0; i--) {
if (array[i]%2 == 0) {
array.splice(i,1);
}
}
It skips the 0 because splice re-indexes the array.
use this:
var array = [2, 5, 9, 14, 0, 1, 3, 6, 7];
for (var i = 0; i < array.length; i++) {
if (array[i]%2 == 0) {
array.splice(i,1);
i = i - 1;
}
}
I've a for loop in javascript shown below. How to convert it to lodash for loop?
In such scenarios using lodash is advantageous over javascript for loop?
I've not used lodash much. Hence please advice.
for (var start = b, i = 0; start < end; ++i, ++start) {
// code goes here
}
You can use lodash range
https://lodash.com/docs/4.17.4#range
_.range(5, 10).forEach((current, index, range) => {
console.log(current, index, range)
})
// 5, 0, [5, 6, 7, 8, 9, 10]
// 6, 1, [5, 6, 7, 8, 9, 10]
// 7, 2, [5, 6, 7, 8, 9, 10]
// 8, 3, [5, 6, 7, 8, 9, 10]
// 9, 4, [5, 6, 7, 8, 9, 10]
// 10, 5, [5, 6, 7, 8, 9, 10]
I will imagine that b = 3 and end = 10 if I run your code and print the variables here is what I will get:
var b = 3;
var end = 10;
for (var start = b, i = 0; start < end; ++i, ++start) {
console.log(start, i);
}
> 3 0
> 4 1
> 5 2
> 6 3
> 7 4
> 8 5
> 9 6
To perform this with lodash (or underscore) I will first generate an array with range then iterate over it and gets the index on each iteration.
Here is the result
var b = 3;
var end = 10;
// this will generate an array [ 3, 4, 5, 6, 7, 8, 9 ]
var array = _.range(b, end);
// now I iterate over it
_.each(array, function (value, key) {
console.log(value, key);
});
And you will get the same result. The complexity is the same as the previous one (so no performance issue).
It seems there is no lodash way for writing loose for loops (those not iterating over a collection), but here is a simplified version of it:
for (var i = 0; i < end - b; i++) {
var start = i + b;
// code goes here
}