forEach() method - looping over an array - javascript

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

Related

Why reduce() is returning NaN when multiplying big array

I'm solving a problem 1822 from leetcode and I'm stuck with reduce() returning NaN.
There is a function signFunc(x) that returns:
1 if x is positive.
-1 if x is negative. 0 if x is equal to 0. You are given an integer array nums. Let product be the product of all values in the array
nums.
Return signFunc(product).
My try of solution:
var arraySign = function(nums) {return Math.sign(nums.reduce((acc, curr) => acc * curr));};
console.log(arraySign([1,5,0,2,-3]));
When I pass simple array like [1,5,0,2,-3] everything is okay, but when I pass monster like
[1,28,-91,-62,-36,-1,-84,-90,-92,61,6,-58,-60,2,51,-15,-18,-81,87,84,100,-84,-13,-87,-33,72,-72,-59,-79,28,-69,-97,-93,17,67,11,-12,19,5,42,-85,71,-77,-82,26,-58,-51,-14,63,-85,-86,66,47,57,-86,-25,-75,59,-17,-71,89,-78,-42,30,39,61,-96,-30,-29,-92,-90,69,20,65,32,92,44,-71,-18,87,-86,23,-96,-21,-49,-96,-98,35,-11,-1,81,-48,68,5,75,57,-30,-7,32,86,-29,-86,-61,45,-31,-93,-26,-9,86,57,-52,75,68,-58,14,27,-94,47,-38,-44,75,-83,21,-83,43,62,74,97,78,43,54,28,64,-19,-89,88,68,18,-96,-83,-25,-71,88,-84,-24,-61,72,-90,-56,29,46,56,51,16,66,-2,65,-95,16,51,42,61,99,89,-93,59,-99,69,26,-61,21,41,40,-4,-49,3,-96,57,65,72,-41,-77,-4,61,71,-88,21,-95,38,64,92,0,-63]
var arraySign = function(nums) {return Math.sign(nums.reduce((acc, curr) => acc * curr));};
console.log(arraySign([1,28,-91,-62,-36,-1,-84,-90,-92,61,6,-58,-60,2,51,-15,-18,-81,87,84,100,-84,-13,-87,-33,72,-72,-59,-79,28,-69,-97,-93,17,67,11,-12,19,5,42,-85,71,-77,-82,26,-58,-51,-14,63,-85,-86,66,47,57,-86,-25,-75,59,-17,-71,89,-78,-42,30,39,61,-96,-30,-29,-92,-90,69,20,65,32,92,44,-71,-18,87,-86,23,-96,-21,-49,-96,-98,35,-11,-1,81,-48,68,5,75,57,-30,-7,32,86,-29,-86,-61,45,-31,-93,-26,-9,86,57,-52,75,68,-58,14,27,-94,47,-38,-44,75,-83,21,-83,43,62,74,97,78,43,54,28,64,-19,-89,88,68,18,-96,-83,-25,-71,88,-84,-24,-61,72,-90,-56,29,46,56,51,16,66,-2,65,-95,16,51,42,61,99,89,-93,59,-99,69,26,-61,21,41,40,-4,-49,3,-96,57,65,72,-41,-77,-4,61,71,-88,21,-95,38,64,92,0,-63]));
I got only "NaN" return. At this moment I skipped this bug by if's:
var arraySign = function(nums) {
let product = nums.reduce((acc, curr) => acc * curr);
if(product>0) return 1;
else if (product<0) return -1;
else return 0;};
But i want to know: why reduce is not working in this problem? Is there any limit for reduce()?
The problem is not with reduce. The problem is that you're multiplying a lot of numbers, which amounts to Infinity (or -Infinity), and then you're also multiplying that by 0. But Infinity * 0 gives NaN.
You can solve this by only multiplying the signs of the numbers:
function arraySign(nums) {
return nums.reduce((acc, curr) => acc * Math.sign(curr), 1);
};
Off Topic: But you can solve this by simply counting the number of negative values and looking for zeroes.
Every 2 negative values, the signs will cancel each other out and the result becomes positive.
an even number of negative values will have a positive result
an odd number of negative values will have a negative result
and the positive values in the list have no influence whatsoever on the sign of the result.
const arraySign = function(nums) {
// if the array contains a `0` the result will be `0`.
// 0 * whatever will always stay 0
if (nums.includes(0)) return 0;
let count = 0;
for (const value of nums) count += value < 0;
return count & 1 ? -1 : 1;
}
const nums = [1, 28, -91, -62, -36, -1, -84, -90, -92, 61, 6, -58, -60, 2, 51, -15, -18, -81, 87, 84, 100, -84, -13, -87, -33, 72, -72, -59, -79, 28, -69, -97, -93, 17, 67, 11, -12, 19, 5, 42, -85, 71, -77, -82, 26, -58, -51, -14, 63, -85, -86, 66, 47, 57, -86, -25, -75, 59, -17, -71, 89, -78, -42, 30, 39, 61, -96, -30, -29, -92, -90, 69, 20, 65, 32, 92, 44, -71, -18, 87, -86, 23, -96, -21, -49, -96, -98, 35, -11, -1, 81, -48, 68, 5, 75, 57, -30, -7, 32, 86, -29, -86, -61, 45, -31, -93, -26, -9, 86, 57, -52, 75, 68, -58, 14, 27, -94, 47, -38, -44, 75, -83, 21, -83, 43, 62, 74, 97, 78, 43, 54, 28, 64, -19, -89, 88, 68, 18, -96, -83, -25, -71, 88, -84, -24, -61, 72, -90, -56, 29, 46, 56, 51, 16, 66, -2, 65, -95, 16, 51, 42, 61, 99, 89, -93, 59, -99, 69, 26, -61, 21, 41, 40, -4, -49, 3, -96, 57, 65, 72, -41, -77, -4, 61, 71, -88, 21, -95, 38, 64, 92, 0, -63];
console.log(arraySign([1,5,2,-3]));
console.log(arraySign(nums));

Javascript changing variable with if statement in forEach

*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;
}
}

Calculate quintiles/deciles from an array of numbers

Given the following array:
[13, 468, 3, 6, 220, 762, 97, 16, 522, 69, 119, 2895, 1255, 49, 19, 261, 9, 140, 55, 20, 6, 22, 6, 17, 115]
I need to calculate the value that is at the 20th, 40th, 60th, and 80th percentile. The steps would be to order the array from low to high, count the total number of values, determine what value is at the 20th percentile, etc. (for example, if there are 10 numbers in order from low to high, the 2nd value would be the 20th percentile).
This is stored in a variable and I know I can sort the numbers like this:
ticks6.sort();
and get the number of values in the array with this:
var newticks=ticks6.length;
I have no idea how to do the next part though where I figure out the percentiles, but looking for a solution in jquery or javascript.
Use like this:
var arr = [13, 468, 3, 6, 220, 762, 97, 16, 522, 69, 119, 2895, 1255, 49, 19, 261, 9, 140, 55, 20, 6, 22, 6, 17, 115];
arr.sort();
var len = arr.length;
var per20 = Math.floor(len*.2) - 1;
console.log(arr[per20]);
//similarly
var per40 = Math.floor(len*.4) - 1;
console.log(arr[per40]);
The Simple Statistics library has a quantile function you can use for this:
ss.quantile([13, 468, 3, 6, 220, 762, 97, 16, 522, 69, 119, 2895, 1255, 49, 19, 261, 9, 140, 55, 20, 6, 22, 6, 17, 115], 0.2)
=> 13
You can easely sort your array :
console.log([13, 468, 3, 6, 220, 762, 97, 16, 522, 69, 119, 2895, 1255, 49, 19, 261, 9, 140, 55, 20, 6, 22, 6, 17, 115].sort(function(a,b){return a-b}))
Get the length of the array : myArray.length.
And the 20th percile parseInt(myArray.length * 0.2) => 2
Something like this:
tricks6.sort();
var length = tricks6.length;
var twentieth = sorted[math.floor((length-1)*.2)] //do for all

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