Javascript Json : Sum values by matching json keys - javascript

My input in one single json
input = [{
"201609": 0,
"201610": 0,
"201611": 0,
"201804": 130,
"201805": 130,
"fy16Q3": 17,
"fy17Q1": 0,
"fy17": 0,
"fy17Q2": 0,
"fy17Q3": 0
}, {
"201510": 0,
"201610": 0,
"201611": 10,
"201803": 20,
"201804": 30,
"201805": 40,
"201806": 130,
"201809": 130,
"fy17Q1": 2,
"fy17": 3,
"fy17Q2": 5,
"fy17Q3": 6
}];
In the output i want to iterate through all the elements of this json and sum the values of the matching keys. Also keep the non matching lone keys in the output as well.
output =
[{
"201510": 5, // no matching pair
"201609": 3, // no matching pair
"201610": 6+9 = 15, // matching pair exist
"201611": 10+12 = 22,
"201803": 20,
"201804": 30+13 = 33,
"201805": 40+14 = 44,
"201806": 130,
"201809": 130,
"fy16Q3": 17, // no matching pair
"fy17Q1": 2+7 = 9, // matching pair exist
"fy17": 3+8 = 11,
"fy17Q2": 5+9 = 14,
"fy17Q3": 6+100 = 106
}];
The problem is that iam not able to figure out how to handle the keys which don't have a matching pair.

You can try the following code. Your desired output looks different than your logic
var data = input = [{
"201609": 0,
"201610": 0,
"201611": 0,
"201804": 130,
"201805": 130,
"fy16Q3": 17,
"fy17Q1": 0,
"fy17": 0,
"fy17Q2": 0,
"fy17Q3": 0
}, {
"201510": 0,
"201610": 0,
"201611": 10,
"201803": 20,
"201804": 30,
"201805": 40,
"201806": 130,
"201809": 130,
"fy17Q1": 2,
"fy17": 3,
"fy17Q2": 5,
"fy17Q3": 6
}];
var output = data.reduce((arr,d,x) =>{
var keys = Object.keys(d);
keys.forEach( (k) => {
if(!arr[k]) arr[k] = 0;
arr[k] = arr[k] + d[k];
})
return arr;
},{});
console.log(output);

input = [{
"201609": 0,
"201610": 0,
"201611": 0,
"201804": 130,
"201805": 130,
"fy16Q3": 17,
"fy17Q1": 0,
"fy17": 0,
"fy17Q2": 0,
"fy17Q3": 0
}, {
"201510": 0,
"201610": 0,
"201611": 10,
"201803": 20,
"201804": 30,
"201805": 40,
"201806": 130,
"201809": 130,
"fy17Q1": 2,
"fy17": 3,
"fy17Q2": 5,
"fy17Q3": 6
}];
var output = input.reduce((p,c) => {
for(let k in c){
p[k] = (p[k] || 0) + c[k];
}
return p;
},{});
console.log(output);

input = [{
"201609": 0,
"201610": 0,
"201611": 0,
"201804": 130,
"201805": 130,
"fy16Q3": 17,
"fy17Q1": 0,
"fy17": 0,
"fy17Q2": 0,
"fy17Q3": 0
}, {
"201510": 0,
"201610": 0,
"201611": 10,
"201803": 20,
"201804": 30,
"201805": 40,
"201806": 130,
"201809": 130,
"fy17Q1": 2,
"fy17": 3,
"fy17Q2": 5,
"fy17Q3": 6
}];
var output = [{}];
for( i in input){
for (key in input[i]){
if(output[0].hasOwnProperty(key)){
output[0][key]+=input[i][key];
}else{
output[0][key]=input[i][key];
}
}
}
console.log(output)

Use array reduce method. In this method take the first object of the input array as the initial object since.SInce object keys are always unique, for any matching key just update the value
var input = [{
"201609": 0,
"201610": 0,
"201611": 0,
"201804": 130,
"201805": 130,
"fy16Q3": 17,
"fy17Q1": 0,
"fy17": 0,
"fy17Q2": 0,
"fy17Q3": 3
}, {
"201510": 0,
"201610": 0,
"201611": 10,
"201803": 20,
"201804": 30,
"201805": 40,
"201806": 130,
"201809": 130,
"fy17Q1": 2,
"fy17": 3,
"fy17Q2": 5,
"fy17Q3": 6
}];
// the array will start reducing from second element that is
// element from index 1
let toLoopArray = input.slice(1, input.length);
let output = input.reduce(function(acc, curr) {
// for the current object check if the key already exist
// if not then create the new key and update value
for (let keys in curr) {
if (!acc.hasOwnProperty(keys)) {
acc[keys] = curr[keys]
} else {
// acc[keys] = acc[keys] + curr[keys]
console.log(curr[keys])
acc[keys] = acc[keys] + curr[keys]
}
}
return acc;
}, input[0])
console.log([output])

Related

convert Buffer to String

I am trying to convert a metatag to plain text using the Buffer.from and .toString(). My goal is to display an array of the keywords using the .map method within my main function. But I notice some strange behavior. My map function isn't displaying the keywords correctly.
Keywords: [79, 0, 98, 0, 115, 0, 116, 0, 59, 0, 80, 0, 101, 0, 114, 0, 115, 0, 111, 0, 110, 0, 59, 0]
const buffer = Buffer.from(Keywords);
buffer:
{"data": [79, 0, 98, 0, 115, 0, 116, 0, 59, 0, 80, 0, 101, 0, 114, 0, 115, 0, 111, 0, 110, 0, 59, 0], "type": "Buffer"}
const bufferString = buffer.toString();
bufferString: Obst;Person;
after returning the bufferString to my main method: Set {"O", "", "b", "s", "t", ";", "P", "e", "r", "o", "n"}
I also tried to use .split()
const words = bufferString.split(";"); => ["Obst", "Person", ""] but when i return this array, then my map function displays only the letter O from the first keyword and no letters from the second keyword.
The strange thing is that when i create a new Array like let keywords = ["Obst", "Person", ""]; everything is working correctly.
So something must be odd with the strings coming from the buffer.
UCS-2 is a character encoding standard in which characters are represented by a fixed-length 16 bits (2 bytes)
With the encoding known you can decode properly and get the data as expected:
const data = [79, 0, 98, 0, 115, 0, 116, 0, 59, 0, 80, 0, 101, 0, 114, 0, 115, 0, 111, 0, 110, 0, 59, 0]
const dataBuffer = Buffer.from(data)
const utf16Decoder = new TextDecoder('UTF-16')
console.log(utf16Decoder.decode(dataBuffer)) // Obst;Person;
I think it's trying to decode as utf8 by default and getting upset at the unrenderable null bytes between every character:

How to insert serial numbers for every object in JavaScript

I am trying to make a javaScript game of housie/bingo game. I used the library npm tambola-generator which returns auto generated tickets.
The server side process generates an array similar to this one ...
[{
"_entries": [[0,17,0,0,41,53,0,78,86], [4,0,0,35,0,58,67,80,0]/*, [ ... ] */],
}, {
"_entries": [[0,16,23,0,41,51,0,0,88], [2,20,0,31,43,56,0,0,0]/*, [ ... ] */],
}, {
"_entries": [[0,0,23,33,0,51,0,73,87], [1,0,0,35,42,58,68,0,0]/*, [ ... ] */],
}, {
// ... more items like that ...
}]
I want each ticket to feature a serial number which should be equal to a ticket items's array index but starting with the base of 1 instead of 0.
How does one include such a ticket number so that I can manage tickets for players?
I am just a beginner I couldn't solve it out. The target structure of the above example code should look like the following one ...
[{
"ticketNum": 1,
"_entries": [[0,17,0,0,41,53,0,78,86], [4,0,0,35,0,58,67,80,0]/*, [ ... ] */],
}, {
"ticketNum": 2,
"_entries": [[0,16,23,0,41,51,0,0,88], [2,20,0,31,43,56,0,0,0]/*, [ ... ] */],
}, {
"ticketNum": 3,
"_entries": [[0,0,23,33,0,51,0,73,87], [1,0,0,35,42,58,68,0,0]/*, [ ... ] */],
}, {
// ... more items like that ...
}]
Just use Array.prototype.map for achieving this task.
const entries = [{
"_entries": [
[0, 17, 0, 0, 41, 53, 0, 78, 86],
[4, 0, 0, 35, 0, 58, 67, 80, 0]
],
}, {
"_entries": [
[0, 16, 23, 0, 41, 51, 0, 0, 88],
[2, 20, 0, 31, 43, 56, 0, 0, 0]
],
}, {
"_entries": [
[0, 0, 23, 33, 0, 51, 0, 73, 87],
[1, 0, 0, 35, 42, 58, 68, 0, 0]
],
}];
const tcktEntries = entries.map((entry, index) => {
return {
ticketNum: index + 1,
...entry
};
});
console.log({
tcktEntries
});
.as-console-wrapper {
min-height: 100%!important;
top: 0;
}

How can I split array of Numbers to individual digits in JavaScript?

I have an array
const myArr = [ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106 ]
I need to split into digits like this:
const splited = [ 9, 4, 9, 5, 9, 6, 9, 7, 9, 8, 9, 9, 1, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, 4, 1, 0, 5, 1, 0, 6 ]
You could join the items, split and map numbers.
var array = [ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106],
pieces = array.join('').split('').map(Number);
console.log(pieces);
Same approach, different tools.
var array = [ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106],
pieces = Array.from(array.join(''), Number);
console.log(pieces);
map each number to a string and split the string, and spread the result into [].concat to flatten:
const myArr = [ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106 ];
const splitted = [].concat(...myArr.map(num => String(num).split('')));
console.log(splitted);
You can use reduce function to create a new array and use split to split the number converted to string
const myArr = [94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106]
let newArr = myArr.reduce(function(acc, curr) {
let tempArray = curr.toString().split('').map((item) => {
return +item;
});
acc.push(...tempArray)
return acc;
}, [])
console.log(newArr)

Extract element having highest attribute value

I have below object, which can have many careerLevels (I have shown 2 for now):
var input =
{
"careerLevel": "Associate",
"careerLevels": [
{
"201609": 21,
"201610": 22,
"201611": 23,
"careerID": "10000120"
},
{
"201609": 31,
"201610": 32,
"201611": 33,
"careerID": "10000130"
}]
};
I want to check careerID attribute and i need to extract that element which has highest careerID value.
So in this case the output will look like :
var output= {"201609": 31,
"201610": 32,
"201611": 33}
What i have tried is as below :
var res = Math.max.apply(Math, oldArr.careerLevels.map(function (o) { return o.careerID; })) // This gives me the highest careerID value
var highestOrderArr = oldArr.careerLevels.filter(element => {
// i think here i need to make a check for the comparison
});
We can use reduce, to get the highest careerID and output that object.
var input ={
"careerLevel": "Associate",
"careerLevels": [
{
"201609": 21,
"201610": 22,
"201611": 23,
"careerID": "10000120"
},
{
"201609": 31,
"201610": 32,
"201611": 33,
"careerID": "10000130"
}]
};
const out = input.careerLevels.reduce((prev, current) => {
return (prev.careerID > current.careerID) ? prev : current
}, false)
console.log(out);
An alternative is sorting and getting the last object.
var input = { "careerLevel": "Associate", "careerLevels": [{ "201609": 21, "201610": 22, "201611": 23, "careerID": "10000120" }, { "201609": 31, "201610": 32, "201611": 33, "careerID": "10000130" } ]},
highest = input.careerLevels.sort((a, b) => a.careerID - b.careerID).pop();
console.log(highest);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using the function reduce
var input = { "careerLevel": "Associate", "careerLevels": [{ "201609": 21, "201610": 22, "201611": 23, "careerID": "10000120" }, { "201609": 31, "201610": 32, "201611": 33, "careerID": "10000130" } ]},
highest = input.careerLevels.reduce((a, c) => c.careerID > a.careerID ? c : a, {careerID: Number.MIN_SAFE_INTEGER});
console.log(highest);
.as-console-wrapper { max-height: 100% !important; top: 0; }

javascript remove duplicates from array of arrays

How to remove duplicates on an array like below:
arr = [
[828, 187, 1, 14, 1, 25, 1417608935730],
[828, 187, 1, 14, 1, 25, 1417608935740],
[828, 187, 1, 14, 1, 25, 1417608935750],
[828, 187, 1, 14, 1, 25, 1417608935760],
[600, 578, 1, 14, 1, 25, 1417608935760],
[828, 187, 1, 14, 1, 25, 1417608935780],
[828, 187, 1, 14, 1, 25, 1417608935790]
]
Since 4th and 5th array have 1417608935760 similar value I want to delete next duplicate and keep only one.
I tried this but not working:
$.each(arr, function(i, insidearr){
if($.inArray(insidearr[6], uniqueNames) === -1)
uniqueNames.push(insidearr);
});
Pls help. Thanks in advance
You're pushing the entire row into uniqueNames. The array will never be equal to the number at the end of each row, so the $.inArray() test will always fail. You need separate arrays for just the element you're comparing and the resulting array.
var newArray = [];
var uniqueNames = {};
$.each(arr, function(i, insidearr) {
if (!(insidearr[6] in uniqueNames)) {
newArray.push(insidearr);
uniqueNames[insidearr[6]] = true;
}
});
I used an object rather than an array for uniqueNames, because searching for an object key is faster than scanning an array.
Just try with:
var uniqueArr = $.grep(arr, function(insidearr){
if ($.inArray(insidearr[6], uniqueNames) === -1) {
uniqueNames.push(insidearr[6]);
return true;
}
});
try this one:
var arr = [
[828, 187, 1, 14, 1, 25, 1417608935730],
[828, 187, 1, 14, 1, 25, 1417608935740],
[828, 187, 1, 14, 1, 25, 1417608935750],
[828, 187, 1, 14, 1, 25, 1417608935760],
[600, 578, 1, 14, 1, 25, 1417608935760],
[828, 187, 1, 14, 1, 25, 1417608935780],
[828, 187, 1, 14, 1, 25, 1417608935790]
];
var len = arr.length;
while(--len) {
if(arr[len][6] == arr[len-1][6]) {
arr.splice(len-1, 1)
}
}
console.log(arr); // here is what you want
If you don't want to manipulate arr, you just need to clone the array by var newArr = arr.slice()

Categories

Resources