Related
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));
*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;
}
}
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
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 .
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.