Counting occurrences of arrays of numbers in Javascript - javascript

How do you count the number of occurrences of number arrays in plain Javascript? Where something like this (imagine having hundreds to these number sets):
[2, 5, 66, 199]
[32, 56, 88, 109]
[13, 45, 102, 200]
[2, 5, 66, 199]
[2, 5, 66, 199]
[32, 56, 88, 109]
would give me back something like this:
2, 5, 66, 199 -> 3 times
32, 56, 88, 109 -> 2 times
13, 45, 102, 200 -> 1 time

Create string from array and use it as key in object. If you want [1, 2] != [2, 1] just remove sort before join method.
const data = [[2, 5, 66, 199],[32, 56, 88, 109],[13, 45, 102, 200],[2, 5, 66, 199],[2, 5, 66, 199],[32, 56, 88, 109]]
const result = data.reduce((r, e) => {
const arr = e.sort().join(',');
r[arr] = (r[arr] || 0) + 1;
return r;
}, {});
console.log(result)

Related

Print all even values in all object key end with odd value

I want to print all even values in all object key end with odd value but the coding I made just now is only specified for arr1, arr3, and arr5. Can anyone suggest me how to fix 'let oddArr' method (maybe in loop) so that when I changed arr1 into arr7, the result would be the same.
var num = {
arr1 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2 : [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3 : [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4 : [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5 : [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
};
let oddArr = [...num.arr1, ...num.arr3, ...num.arr5] //need some correction here
let evenNum = oddArr.filter(number => number % 2 == 0);
console.log(evenNum.toString());
//help me fix 'let oddArr' (maybe in loop method) so that when I changed the object of the array (e.g: arr1 -> arr7) it would come out with the same result
//the result/output should be 2,4,6,8,10,22,24,26,28,30,42,44,46,48,50 based on var num
You can try like below using for in loop and it works with any last character as odd.
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr7: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
};
let oddArr = [];
for (let key in num) {
if (key.charAt(key.length - 1) % 2 !== 0) {
oddArr = [...oddArr, ...num[key]];
}
}
let evenNum = oddArr.filter((number) => number % 2 === 0);
console.log(evenNum.toString());
You might want to use
let oddArr = Object.entries(num).filter( // filter key names
e => +e[0].replace("arr", '') % 2 !== 0 // replace "arr" and check if X in arrX is odd
).map(e => e[1]).flat() // merge values and flattern array
You can also make use of regex if the "arrX"-naming is not consistent:
+e[0].match(/\d+/) % 2 !== 0
See a working snippet below:
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
};
let oddArr = Object.entries(num).filter(
e => +e[0].replace("arr", '') % 2 !== 0
).map(e => e[1]).flat()
let evenNum = oddArr.filter(number => number % 2 == 0);
console.log(evenNum.toString());
This also works.
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
arr6: [51, 52, 53, 55, 55, 56, 57, 58, 59, 60],
arr7: [61, 62, 63, 66, 65, 66, 67, 68, 69, 70],
};
var evenNums = Object.keys(num).filter((item) => {
itemNum = item.replace("arr", "");
return itemNum % 2 !== 0;
}).map((o) => num[o]).flat().filter((x) => x % 2 == 0);
console.log(evenNums);

Why is this returning false? (Simple code) [duplicate]

This question already has answers here:
How to compare arrays in JavaScript?
(61 answers)
Triple equal signs return false for arrays in javascript. why?
(4 answers)
Closed 1 year ago.
This is a simple code designed to tell me if one array has an array equal to it in an array consisting of arrays. So the following function should be returning true but it returns false.
var TransferR =[0,8,16,24,32,40,48,56]
var rookV =[
[0,8,16,24,32,40,48,56],
[1,9,17,25,33,41,49,57],
[2,10,18,26,34,42,50,58],
[3,11,19,27,35,43,51,59],
[4,12,20,28,36,44,52,60],
[5,13,21,29,37,45,53,61],
[6,14,22,30,38,46,54,62],
[7,15,23,31,39,47,55,63],
]
const match = rookV.some(memb=> memb === TransferR)
console.log(match)
You can't compare arrays with ===, which compares the references.
Compare array length and then each value.
For example:
const match = rookV.some(memb=> {
memb.length === TransferR.length && memb.every(el => TransferR.includes(el))
});
This code will first check that there is a match in the length (so it will skip arrays that are uncomparable), and than will check that every element of memb is included in the TransferR array, returning true or false.
how about stringify it?
var TransferR = [0, 8, 16, 24, 32, 40, 48, 56]
var rookV = [
[0, 8, 16, 24, 32, 40, 48, 56],
[1, 9, 17, 25, 33, 41, 49, 57],
[2, 10, 18, 26, 34, 42, 50, 58],
[3, 11, 19, 27, 35, 43, 51, 59],
[4, 12, 20, 28, 36, 44, 52, 60],
[5, 13, 21, 29, 37, 45, 53, 61],
[6, 14, 22, 30, 38, 46, 54, 62],
[7, 15, 23, 31, 39, 47, 55, 63],
]
const match = rookV.some(
memb => JSON.stringify(memb) === JSON.stringify(TransferR))
console.log(match)

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!

Transform a 9x9 Matrix so that each row is a 3x3 Block

I have the following example data:
[0] = {01,02,03, 04,05,06, 07,08,09}
[1] = {11,12,13, 14,15,16, 17,18,19}
[2] = {21,22,23, 24,25,26, 27,28,29}
[3] = {31,32,33, 34,35,36, 37,38,39}
[4] = {41,42,43, 44,45,46, 47,48,49}
[5] = {51,52,53, 54,55,56, 57,58,59}
[6] = {61,62,63, 64,65,66, 67,68,69}
[7] = {71,72,73, 74,75,76, 77,78,79}
[8] = {81,82,83, 84,85,86, 87,88,89}
To create the new matrix I did this, Knowing it static 9x9
var grid2=[[],[]];
grid2.push([grid[0][0],grid[0][1], grid[0][2],grid[1][0],grid[1][1], grid[1][2],grid[2][0],grid[2][1], grid[2][2]]);
grid2.push([grid[3][0],grid[3][1], grid[3][2],grid[4][0],grid[4][1], grid[4][2],grid[5][0],grid[5][1], grid[5][2]]);
grid2.push([grid[6][0],grid[6][1], grid[6][2],grid[7][0],grid[7][1], grid[7][2],grid[8][0],grid[8][1], grid[8][2]]);
grid2.push([grid[0][3],grid[0][4], grid[0][5],grid[1][3],grid[1][4], grid[1][5],grid[2][3],grid[2][4], grid[2][5]]);
grid2.push([grid[3][3],grid[3][4], grid[3][5],grid[4][3],grid[4][4], grid[4][5],grid[5][3],grid[5][4], grid[5][5]]);
grid2.push([grid[6][3],grid[6][4], grid[6][5],grid[7][3],grid[7][4], grid[7][5],grid[8][3],grid[8][4], grid[8][5]]);
grid2.push([grid[0][6],grid[0][7], grid[0][8],grid[1][6],grid[1][7], grid[1][8],grid[2][6],grid[2][7], grid[2][8]]);
grid2.push([grid[3][6],grid[3][7], grid[3][8],grid[4][6],grid[4][7], grid[4][8],grid[5][6],grid[5][7], grid[5][8]]);
grid2.push([grid[6][6],grid[6][7], grid[6][8],grid[7][6],grid[7][7], grid[7][8],grid[2][6],grid[8][7], grid[8][8]]);
This works, but my question is, can this be done more efficiently / elegantly.
The point of this, is part of a larger code base, that takes the matrix and validates if it is a Sudoku solution.
You can use a simple algorithm for this
let idx = [0, 1, 2], idy = [0, 1, 2];
let result = [];
for(let i=0; i<9; i+=3){
for(let j=0; j<9; j+=3){
idx.forEach(e => {
idy.forEach(f => {
result.push(arr[i+e][j+f]);
})
})
}
}
You could take a nested approach for transforming the given 2D to a 4D array.
var data = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [11, 12, 13, 14, 15, 16, 17, 18, 19], [21, 22, 23, 24, 25, 26, 27, 28, 29], [31, 32, 33, 34, 35, 36, 37, 38, 39], [41, 42, 43, 44, 45, 46, 47, 48, 49], [51, 52, 53, 54, 55, 56, 57, 58, 59], [61, 62, 63, 64, 65, 66, 67, 68, 69], [71, 72, 73, 74, 75, 76, 77, 78, 79], [81, 82, 83, 84, 85, 86, 87, 88, 89],],
result = data.reduce((r, a, i) => (
a.forEach((b, j) =>
[Math.floor(i / 3), Math.floor(j / 3), i % 3].reduce(
(s, k) => s[k] = s[k] || [],
r
)[j % 3] = b),
r),
[]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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 .

Categories