Javascript changing variable with if statement in forEach - javascript

*Use the existing test variable and write a forEach loop
* that adds 100 to each number that is divisible by 3.
*
* Things to note:
* - you must use an if statement to verify code is divisible by 3
I'm confused, why isn't my code working?
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139
];
test.forEach(function(number) {
if (number % 3 === 0) {
number += 100;
});
console.log(test[0]); **this is returning 12, NOT the desired 112**

You are not putting back the number in array.
Primitives are not references. You need to use the index and put it back.
test.forEach(function(number,index) {
if (number % 3 === 0) {
number += 100;
test[index] = number;
});

You can write a function that doesn't need to access its scope like some of the other answers here do, using forEach()'s third argument:
arr.forEach(function callback(currentValue, index, array) { ...
let test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139
]
test.forEach(function (number, index, array) {
if (number % 3 === 0) {
array[index] = number + 100
}
})
console.log(test[0])

You need to include index in your for-each loop. and use that index to change value in actual array.
working code:
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139
];
test.forEach(function(number, i) {
if (number % 3 === 0) {
test[i] += 100;
}
});
console.log(test[0]); //print 112

As others have said, you need to set the index from which the number was read to the value+100
Javascript has a lot of not-so-intuitive quirks, and function arguments spare no expense. Check out this article for a bit more detail about how Javascript passes values/references to functions: https://stackoverflow.com/a/6605700/1690165

you can use forloop/foreach:
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139 ];
foreach
foreach (int i in test)
{
if (i % 3 === 0) {
i += 100;
}
}
forloop
for (i = 0; i < test.Count; i++)
{
if (test[i] % 3 === 0) {
test[i] += 100;
}
}

Related

forEach() method - looping over an array

I am totally new to coding so my question is probably very basic. I want to loop over the following array and every time the number is divisible by 3 I want to add 100. If not, just print the number. I want to do that with the forEach() method. This is my code but when I want to print it it says "undefined" What am I doing wrong?
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139];
test.forEach(function(num){
if(num %3 === 0){
return num+=100;
}else{
return num;
}
console.log(num) ;
})
Get rid of the return statements:
The return statement ends function execution and specifies a value to
be returned to the function caller.
Therefore it will never make it to the console.log line (this is what they call unreachable code since there is no possible path to it):
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139
];
test.forEach(function(num) {
if (num % 3 === 0) {
num += 100;
}
console.log(num);
})
I removed the else block because, as pointed out in the comments below, there is no purpose for it.
The approach above is fine if all you want to do is log the result, but if you want to get a new array that has stored all the new values then you should consider using Array.prototype.map like this:
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139
];
var updatedValues = test.map(num => num % 3 === 0 ? num + 100 : num);
console.log(updatedValues);
The problem is that the return keyword immediately stops the function, so you don't progress further. And since Array#forEach itself doesn't return anything, the keyword is pretty useless. You can just remove it and you'd get the behaviour you want:
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139];
test.forEach(function(num){
if(num %3 === 0){
num+=100;
}
console.log(num) ;
})
If you instead want to create a new array from the first one using the rules you've described, then you can simply substitute .forEach for the Array#map method:
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139];
var result = test.map(function(num){
if(num %3 === 0){
return num+=100;
}else{
return num;
}
})
console.log(result);
You should use map instead of forEach here since map will execute the provided function to each array item and return a new array.
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
Source
Just changing your current code, it can be like this
var test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4,
19, 300, 3775, 299, 36, 209, 148, 169, 299,
6, 109, 20, 58, 139, 59, 3, 1, 139];
var result = test.map(function(num) {
if (num %3 === 0) {
return num + 100;
} else {
return num;
}
})
Or, you can also improve it further by separating things
const add100IfDividableBy3 = function (num) {
return (num % 3 === 0) ? num + 100 : num;
}
const test = [12, 929, 11, 3, 199, 1000, 7, 1, 24, 37, 4, 19, 300, 3775, 299, 36, 209, 148, 169, 299, 6, 109, 20, 58, 139, 59, 3, 1, 139];
const result = test.map(add100IfDividableBy3)
The function add100IfDividableBy3 uses what is called as a Ternary Operator

How to find the Minimum number of swaps required for sorting an array of numbers in descending order in javascript

I'm trying to get my code to do this:
Original array = [1,2,3,4] swap once-> [4,2,3,1] swap again->[4,3,2,1]
Therefore result is 2
But it's not working. Here's what I have so far:
function check(arr){
var sarr = [];
var cnt = 0;
var arrL = arr.length;
// Create a second copy of the array for reference
var arrCopy = [...arr];
for(let i=0; i<arrL;i++){
var maxV = Math.max(...arr);
sarr.push(maxV);
let pos = arr.indexOf(maxV);
// Remove the found number
arr.splice(pos,1);
// Check if the index of the number in the new array is same with the copy, if not then there was a swap
let ai =arrCopy.indexOf(maxV);
let si =sarr.indexOf(maxV);
if (ai !== si && (i+1)!=arrL && pos !== 0){
cnt++;
};
}
console.log(cnt);
}
check([1, 2, 3, 4, 5, 6]);//Result should be 3
check([6,5,4,3,2,1]); //result should be 0
check([1,2,3,4]); //result should be 2
check([1,3,2,5,4,6]); //result should be 3
check([1,2,10,4,5,6,7,8,9,3,12,11]);//result should be 6
check([ 49, 37, 9, 19, 27, 3, 25, 11, 53,  42, 57, 50, 55,  56, 38, 48, 6, 33, 28, 8, 20, 31, 51, 14, 23, 4, 58, 52, 36, 22, 41, 47, 39, 2, 7, 13, 45, 1, 44, 32, 10, 15, 21, 30, 17,  60, 29, 5, 59, 12, 40, 24, 54, 46, 26, 43, 35, 34, 18, 16]);//result should be 54
Can someone please let me know what I'm doing wrong?
I would start with a copy of the array in descending order for getting the right index of the items.
For practical reasons, (or just a shorter conception of the loop with including check and decrement), I loop from the end of the array.
Then I check the value of array and reversed at the dame index and go on with the iteration.
If not the same value, the items at the wanted position i and the actual position p are swapped and the count incremented.
At the end the count is returned.
function check(array) {
var reversed = array.slice().sort((a, b) => b - a),
count = 0,
i = array.length,
p;
while (i--) {
if (array[i] === reversed[i]) continue;
p = array.indexOf(reversed[i]);
[array[i], array[p]] = [array[p], array[i]];
count++;
}
console.log(...array);
return count;
}
console.log(check([1, 2, 3, 4, 5, 6])); // 3
console.log(check([6, 5, 4, 3, 2, 1])); // 0
console.log(check([1, 2, 3, 4])); // 2
console.log(check([1, 3, 2, 5, 4, 6])); // 3
console.log(check([1, 2, 10, 4, 5, 6, 7, 8, 9, 3, 12, 11])); // 6
console.log(check([ 49, 37, 9, 19, 27, 3, 25, 11, 53,  42, 57, 50, 55,  56, 38, 48, 6, 33, 28, 8, 20, 31, 51, 14, 23, 4, 58, 52, 36, 22, 41, 47, 39, 2, 7, 13, 45, 1, 44, 32, 10, 15, 21, 30, 17,  60, 29, 5, 59, 12, 40, 24, 54, 46, 26, 43, 35, 34, 18, 16])); // 54
.as-console-wrapper { max-height: 100% !important; top: 0; }
function minimumSwaps(arr) {
var count = 0;
arr.sort((a, b) => {
if (a < b) {
count++;
}
});
return count;
}
console.log(minimumSwaps([1, 2, 3, 4, 7, 6, 5]));

I am stuck on a quiz in Udacity for JavaScript on Multi-dimensional arrays.

The quiz is about a multidimensional array and wants us to use a nested for loop to cycle through each element and replace the values that are divisible by 2 with the strings 'even' and 'odd' for even and odd numbers respectively. I cannot print out the array with the numbers divisible by 2 on to the console with the added string.
I have tried using .slice() and .splice() also but that did not get me the desired results either. Below is my latest attempt.
Programming Quiz - Multi-dimensional Arrays:
Question: Use a nested for loop to take the numbers array below and replace all of the values that are divisible by 2 (even numbers) with the string "even" and all other numbers with the string "odd".
var numbers = [
[243, 12, 23, 12, 45, 45, 78, 66, 223, 3],
[34, 2, 1, 553, 23, 4, 66, 23, 4, 55],
[67, 56, 45, 553, 44, 55, 5, 428, 452, 3],
[12, 31, 55, 445, 79, 44, 674, 224, 4, 21],
[4, 2, 3, 52, 13, 51, 44, 1, 67, 5],
[5, 65, 4, 5, 5, 6, 5, 43, 23, 4424],
[74, 532, 6, 7, 35, 17, 89, 43, 43, 66],
[53, 6, 89, 10, 23, 52, 111, 44, 109, 80],
[67, 6, 53, 537, 2, 168, 16, 2, 1, 8],
[76, 7, 9, 6, 3, 73, 77, 100, 56, 100]
];
My code:
//create a nested for loop to cycle through each row and column
for(let row = 0; row < numbers.length; row++){
for(let col = 0; col < numbers.length; col++){
//if the even numbers in each row and column are divisible by 2, replace those
//numbers with the word even
if(numbers % 2 === 0){
numbers[row] += 'even';
}
}
}
console.log(numbers);
You're real close! It comes down to how you're referencing the index in the 2-dimensional array. Iterating over it in a nested for loop requires first that we iterate through the rows, then the columns. In your example, you were actually iterating over the columns twice. In order to fix this, you would simply iterate over the row index of the numbers array in the nested for loop:
for(let row = 0; row < numbers.length; row++){
for(let col = 0; col < numbers[row].length; col++){
Then finally you will need to set the target index numbers[row][col] to even. In your example you used the addition assignment operator +=, which performs what is string concatenation. Instead of simply changing the index value to 'even', the += would actually add the word 'even' to the end of the number. So the index output would actually read something like 156even. Just drop the plus sign in order to reassign the index to even:
numbers[row][col] = 'even';
var numbers = [
[243, 12, 23, 12, 45, 45, 78, 66, 223, 3],
[34, 2, 1, 553, 23, 4, 66, 23, 4, 55],
[67, 56, 45, 553, 44, 55, 5, 428, 452, 3],
[12, 31, 55, 445, 79, 44, 674, 224, 4, 21],
[4, 2, 3, 52, 13, 51, 44, 1, 67, 5],
[5, 65, 4, 5, 5, 6, 5, 43, 23, 4424],
[74, 532, 6, 7, 35, 17, 89, 43, 43, 66],
[53, 6, 89, 10, 23, 52, 111, 44, 109, 80],
[67, 6, 53, 537, 2, 168, 16, 2, 1, 8],
[76, 7, 9, 6, 3, 73, 77, 100, 56, 100]
];
for(let row = 0; row < numbers.length; row++){
for(let col = 0; col < numbers[row].length; col++){ //iterate over the n-th index of numbers[]
if(numbers[row][col] % 2 === 0){ //numbers[row][col] points to the nested index
numbers[row][col] = 'even'; //set index to 'even'
}
}
}
console.log(numbers);
This video is a nice explanation of how iterating over 2d arrays works: https://www.youtube.com/watch?v=qdT1P2qmsmU
The video is using Java, but the idea is exactly the same.
Hope this helps! Multi-dimensional arrays are tough to wrap your brain around!

Convert buffer to array

I am setting memcached with
$memcached->set("item" , ["1" => "hello"]);
anything work in PHP ,
In Node.js with memcached plugin , I get a buffer instead of array in result
<Buffer 61 3a 25 61 34 3a>
I can not convert such buffer to array
In Node.js :
memcached.get("item" , function(err, data) {
console.log(data);
}
Do you have any way ?
arr = [...buffer]
ES6 introduced a lot of other features, besides buffers.
You can even easily append like this:
arr.push(...buffer)
The ... operator expands enumerables such as arrays and buffers when used in array. It also expands them into separate function arguments.
Yes, it's also faster:
... : x100000: 835.850ms
Slice call from prototype : x100000: 2118.513ms
var array,
buffer = new Buffer([1, 4, 4, 5, 6, 7, 5, 3, 5, 67, 7, 4, 3, 5, 76, 234, 24, 235, 24, 4, 234, 234, 234, 325, 32, 6246, 8, 89, 689, 7687, 56, 54, 643, 32, 213, 2134, 235, 346, 45756, 857, 987, 0790, 89, 57, 5, 32, 423, 54, 6, 765, 65, 745, 4, 34, 543, 43, 3, 3, 3, 34, 3, 63, 63, 35, 7, 537, 35, 75, 754, 7, 23, 234, 43, 6, 247, 35, 54, 745, 767, 5, 3, 2, 2, 6, 7, 32, 3, 56, 346, 4, 32, 32, 3, 4, 45, 5, 34, 45, 43, 43]),
iter = 100000;
array = buffer;
console.time("... : x" + iter);
for (var i = iter; i--;) array = [...buffer]
console.timeEnd("... : x" + iter);
console.time("Apply/call/etc : x" + iter);
for (var i = iter; i--;) array = Array.prototype.slice.call(buffer, 0)
console.timeEnd("Apply/call/etc : x" + iter);
There is another way to convert to array of integers
Using toJSON()
Buffer.from('Text of example').toJSON()
{ type: 'Buffer',data: [ 84, 101, 120, 116, 32, 111, 102, 32, 101, 120, 97, 109, 112, 108, 101 ] }
// simple get data
Buffer.from('Text of example').toJSON().data
[ 84, 101, 120, 116, 32, 111, 102, 32, 101, 120, 97, 109, 112, 108, 101 ]
Example of benchmark
// I took this from #user4584267's answer
const buffer = new Buffer([1, 4, 4, 5, 6, 7, 5, 3, 5, 67, 7, 4, 3, 5, 76, 234, 24, 235, 24, 4, 234, 234, 234, 325, 32, 6246, 8, 89, 689, 7687, 56, 54, 643, 32, 213, 2134, 235, 346, 45756, 857, 987, 0790, 89, 57, 5, 32, 423, 54, 6, 765, 65, 745, 4, 34, 543, 43, 3, 3, 3, 34, 3, 63, 63, 35, 7, 537, 35, 75, 754, 7, 23, 234, 43, 6, 247, 35, 54, 745, 767, 5, 3, 2, 2, 6, 7, 32, 3, 56, 346, 4, 32, 32, 3, 4, 45, 5, 34, 45, 43, 43]);
let array = null;
const iterations = 100000;
console.time("...buffer");
for (let i = iterations; i=i-1;) array = [...buffer]
console.timeEnd("...buffer");
console.time("array.prototype.slice.call");
for (let i = iterations; i=i-1;) array = Array.prototype.slice.call(buffer, 0)
console.timeEnd("array.prototype.slice.call");
console.time("toJSON().data");
for (let i = iterations; i=i-1;) array = buffer.toJSON().data
console.timeEnd("toJSON().data");
OUTPUT
...buffer: 559.932ms
array.prototype.slice.call: 1176.535ms
toJSON().data: 30.571ms
or if you want more profesional and custom function in Buffer use this:
Buffer.prototype.toArrayInteger = function(){
if (this.length > 0) {
const data = new Array(this.length);
for (let i = 0; i < this.length; i=i+1)
data[i] = this[i];
return data;
}
return [];
}
Example of benchmark:
const buffer = new Buffer([1, 4, 4, 5, 6, 7, 5, 3, 5, 67, 7, 4, 3, 5, 76, 234, 24, 235, 24, 4, 234, 234, 234, 325, 32, 6246, 8, 89, 689, 7687, 56, 54, 643, 32, 213, 2134, 235, 346, 45756, 857, 987, 0790, 89, 57, 5, 32, 423, 54, 6, 765, 65, 745, 4, 34, 543, 43, 3, 3, 3, 34, 3, 63, 63, 35, 7, 537, 35, 75, 754, 7, 23, 234, 43, 6, 247, 35, 54, 745, 767, 5, 3, 2, 2, 6, 7, 32, 3, 56, 346, 4, 32, 32, 3, 4, 45, 5, 34, 45, 43, 43]);
let array = null;
const iterations = 100000;
console.time("toArrayInteger");
for (let i = iterations; i=i-1;) buffer.toArrayInteger();
console.timeEnd("toArrayInteger");
Ouput:
toArrayInteger: 28.714ms
Note: In the last example I copied a function from Buffer.toJSON and custom it a lite
Here you go:
var buffer = new Buffer([1,2,3])
var arr = Array.prototype.slice.call(buffer, 0)
console.log(arr)
I haven't used memcached so I am not sure just what this buffer represents or what you want to have instead. Sorry. Here is a function to split a buffer up into an array of bytes. More at node.js Buffer docs, hope it helps!
var hex = new Buffer("613a2561343a", "hex");
var l = hex.length; // in bytes
var output = [];
for(var i = 0; i < l; i++){
var char = hex.toString('hex',i,i+1); // i is byte index of hex
output.push(char);
};
console.log(output);
// output: [ '61', '3a', '25', '61', '34', '3a' ]
You can also use Array.from:
memcached.get("item" , function(err, data) {
console.log(Array.from(data));
}
I have a solution, although I am currently trying to find a better one:
function bufToArray(buffer) {
let array = new Array();
for (data of buffer.values()) array.push(data);
return array;
}
EDIT : I found a simpler way:
var buffer = Buffer.from('NodeJS rocks!')
var array = new Function(`return [${Array.prototype.slice.call(buffer, 0)}]`)
But, like someone already said, [...buffer] is faster (and more code efficient).
You can also use new Uint8Array(buffer [, byteOffset [, length]]);
In interent , there was no information about that , but I have found the convert way
In nodejs , I have to use :
var arrayobject = phpjs.unserialize(data.toString());
but , it is very stupid way for getting array , it seem that php serilzie the data when setting memcache .

Weird jsPerf behavior for recursive function

I have the following code in a test case on jsPerf:
var arr = [0, 45, 96, 8, 69, 62, 80, 91, 89, 24, 6, 23, 49, 88, 26, 40, 87, 61, 83, 2, 60, 53, 43, 82, 67, 3, 65, 37, 42, 77, 73, 38, 9, 46, 75, 10, 63, 15, 47, 28, 79, 55, 59, 95, 11, 93, 70, 98, 25, 48, 30, 5, 72, 12, 84, 1, 29, 13, 50, 33, 19, 7, 31, 57, 32, 44, 74, 51, 35, 90, 86, 54, 4, 64, 92, 71, 22, 41, 16, 17, 27, 76, 39, 18, 99, 94, 36, 66, 85, 20, 21, 56, 34, 81, 14, 78, 68, 58, 97, 52];
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
function quicksort( arr ) {
if ( arr.length <= 1 )
return arr;
var i = 0,
len = arr.length,
less = [],
greater = [],
random = Math.floor( Math.random() * len ),
pivot = arr[ random ];
arr.remove( random );
for ( ; i < len - 1; i++ ){
if ( arr[ i ] <= pivot )
less.push( arr[ i ] );
else
greater.push( arr[ i ] );
}
return quicksort( less ).concat( pivot, quicksort( greater ) );
};
If you copy that into your console and run quicksort( arr ), you'll see that it correctly returns a sorted array.
But for some reason, in this test case on jsPerf, my quicksort function seems to be returning only a single number ( as can be seen in 'Perparation Code Output' ). It also seems to be running way faster than it probably should.
Anybody ideas into what's going on would be greatly appreciated.
I think the problem is that you're calling that .remove() function on the original array, so it quickly strips it down to nothing. In other words, each initial call to the quicksort function removes an element.
When I make it create a copy of the array first, then it seems to work.

Categories