Appending last JSON object to the previous in array - javascript

I have a function that is outputting an array of json objects, where the last one is unique in structure:
// multi
[
{ "min": 10, "max": 200, "sum": 580, "avg": 72.5 },
{ "min": 10, "max": 470, "sum": 8300, "avg": 103.75 },
{ "largest": 470 }
]
// single
[
{ "min": 20, "max": 190, "sum": 270, "avg": 90 },
{ "largest": 190 }
]
Is it possible to have it append the last part { "largest": n } to the other objects in the array?
So the output would be:
// multi
[ { "min": 10, "max": 200, "sum": 580, "avg": 72.5, "largest": 470 },
{ "min": 10, "max": 470, "sum": 8300, "avg": 103.75, "largest": 470 }
]
// single
[
{ "min": 20, "max": 190, "sum": 270, "avg": 90, "largest": 190 }
]
Here is a link to the snippet of code that outputs the above.

Slice the array to omit the last entry, then map each entry to merge in the last entry
function mergeLastEntry(arr) {
const last = arr[arr.length - 1] // get the last entry
// map each object (except the last) to merge in the `last` object
return arr.slice(0, -1).map(o => ({ ...o, ...last }))
}
const multi =[{"min":10,"max":200,"sum":580,"avg":72.5},{"min":10,"max":470,"sum":8300,"avg":103.75},{"largest":470}]
const single = [{"min":20,"max":190,"sum":270,"avg":90},{"largest":190}]
console.log("multi", mergeLastEntry(multi))
console.log("single", mergeLastEntry(single))
.as-console-wrapper { max-height: 100% !important; }

Related

I'd like to filter out objects which do not have an ext key on them

How can I remove objects which do not have an ext key? I want to take pictures, but there is a problem because some objects do not have a picture. I'm confused about filtering. Can it be done with reduce or filter?
{
"posts": [
{
"filename": "1647706792183",
"ext": ".png",
"w": 300,
"h": 450,
"tn_w": 166,
"tn_h": 250,
"tim": 1664328637690788,
"time": 1664328637,
"md5": "Omk9VtmPOD1U38U1OOAP/w==",
"fsize": 200271,
"resto": 0,
"country": "DK",
"bumplimit": 0,
"imagelimit": 0,
"semantic_url": "f1-relentless-formula-one-general-all-smiles",
"replies": 378,
"images": 155,
"unique_ips": 102,
"tail_size": 50
},
{
"now": "09/27/22(Tue)21:31:17",
"name": "Anonymous",
"resto": 123946553,
}
]
}
You can use .filter to run a function that returns true/false for each item of your data.
const data = { posts: [ .... ] };
const postsWithExt = data.posts.filter(post => post.ext !== undefined);
If you want to filter falsy values for .ext then use
posts.filter(post => !post.ext)
You can just filter your posts array where the ext property exists.
e.g.
const data = {
"posts": [{
"filename": "1647706792183",
"ext": ".png",
"w": 300,
"h": 450,
"tn_w": 166,
"tn_h": 250,
"tim": 1664328637690788,
"time": 1664328637,
"md5": "Omk9VtmPOD1U38U1OOAP/w==",
"fsize": 200271,
"resto": 0,
"country": "DK",
"bumplimit": 0,
"imagelimit": 0,
"semantic_url": "f1-relentless-formula-one-general-all-smiles",
"replies": 378,
"images": 155,
"unique_ips": 102,
"tail_size": 50
},
{
"now": "09/27/22(Tue)21:31:17",
"name": "Anonymous",
"resto": 123946553,
}
]
};
const result = data.posts.filter(x => x.ext);
console.log(result);

Get values from multidimensional object to list

I have object:
data = {
"usa": {
"a": {
"min": 1,
"max": 2,
"avg": 1.5
},
"b": {
"min": 3,
"max": 5,
"avg": 4
}
},
"canada": {
"c": {
"min": 1,
"max": 2,
"avg": 1.5
}
}
}
I would like receive all max values from second dimension, for example:
function getMaxValues(country: string): number[] {
const maxValues: number[] = data[country]???
return maxValues;
}
I any better way than iterate over this object and collect results? In other languages are special functions for this. I don't want use iteration because this object is very large and usually specific functions for this are more efficient.
You can do:
Object.values(data).flatMap((country) => {
return Object.values(country).map(({max}) => max);
});
You need to get the country object values then map to get max value.
let data = {
"usa": {
"a": {
"min": 1,
"max": 2,
"avg": 1.5
},
"b": {
"min": 3,
"max": 5,
"avg": 4
}
},
"canada": {
"c": {
"min": 1,
"max": 2,
"avg": 1.5
}
}
}
function getMaxValues(country) {
const maxValues = Object.values(data[country]).map(v => v.max);
return maxValues;
}
console.log(getMaxValues('usa'));
You can reduce the entries of the object:
const data = {
"usa": {
"a": {
"min": 1,
"max": 2,
"avg": 1.5
},
"b": {
"min": 3,
"max": 5,
"avg": 4
}
},
"canada": {
"c": {
"min": 1,
"max": 2,
"avg": 1.5
}
}
};
const maxValuesPerCountry = Object.entries(data)
.reduce( (acc, [key, value]) =>
( {...acc, [key]: Object.entries(value).map(([, v]) => v.max) } ), {} );
console.log(maxValuesPerCountry);
console.log(`usa: ${maxValuesPerCountry.usa}`);
.as-console-wrapper {
max-height: 100% !important;
}

Stacked D3 bar chart with multiple level

I want to create a responsive D3 bar chart using my JSON.
I tried pushing my values into an array and create a bar chart using the same array. But it didn't come out well. I don't know what I am missing.
Can anyone please help me with this?
JSON = {
"Resource 1": {
"metrics": [
{
"2021-04-07": {
"percent": {
"avg": 15,
"max": 30,
"min": 10
}
}
},
{
"2021-04-08": {
"percent": {
"avg": 30,
"max": 50,
"min": 12
}
}
},
{
"2021-04-09": {
"percent": {
"avg": 35,
"max": 60,
"min": 5
}
}
}
]
},
"Resource 2": {
"metrics": [
{
"2021-04-07": {
"percent": {
"avg": 30,
"max": 50,
"min": 10
}
}
},
{
"2021-04-08": {
"percent": {
"avg": 15,
"max": 30,
"min": 10
}
}
},
{
"2021-04-09": {
"percent": {
"avg": 27,
"max": 39,
"min": 15
}
}
}
]
}
}
My y-axis will be numeric with a maximum value = 100 and the x-axis will be a date.
1 whole bar = 1 Resource, each resource contains three segments (Minimum, Average, and Maximum) stacked one above the other.
Each date will have multiple resources. When the cursor moved to the minimum value of resource1 in one date, it should highlight all the minimum value of the same resource1 on others dates too.
While moving the cursor to the bar the tooltip should show the resource name with resource value like
Resource1
min: 10
I have attached my fiddle.
https://jsfiddle.net/oLqdrymh/
Thanks in advance.

Change format of JSON using Javascript

Alright, so in my code I grab a JSON blob that looks like this:
[
{
"ts": 1431736740,
"aggs": {
"DNS": {
"min": 20,
"max": 21,
},
"SEND": {
"min": 102,
"max": 8114,
},
"SSL": {
"min": 110,
"max": 7806,
},
"SERVERBUSY": {
"min": 1360,
"max": 13709,
}
}
},
{
"ts": 1431736680,
"aggs": {
"DNS": {
"min": 22,
"max": 24,
},
"SEND": {
"min": 210,
"max": 8251,
},
"SSL": {
"min": 117,
"max": 12488,
},
"SERVERBUSY": {
"mn": 6462,
"max": 9800,
}
}
},
{
"ts": 1431736620,
"aggs": {
"DNS": {
"min": 21,
"max": 22,
},
"SEND": {
"min": 92,
"max": 12035,
},
"SSL": {
"min": 111,
"max": 9758,
},
"SERVERBUSY": {
"min": 9855,
"max": 14112,
}
}
}
]
and I need help converting it into one that looks like this:
[
{
"key": "DNS",
"values": [
[
0, //The first number just goes up by one.
20 //The second number is the value of aggs.DNS.min
],
[
1,
22
],
[
2,
21
]
]
},
{
"key": "SEND",
"values": [
[
0,
102
],
[
1,
210
],
[
2,
92
]
]
},
{
"key": "SSL",
"values": [
[
0,
110
],
[
1,
117
],
[
2,
111
]
]
},
{
"key": "SERVERBUSY",
"values": [
[
0,
1360
],
[
1,
6462
],
[
2,
9855
]
]
}
]
Because I'm using a library that only uses JSONs in that correct format. Is this possible? I have found a few different questions that show you can change JSON format, but I'm not sure if it can be done that dramatically. Any help is much appreciated!!!
Alright, I wanted to post what I figured out in case it helps anyone else:
var pagestatsObject = {};
var dnsValues = [];
for(var i=0; i<bardata.length; i++){
var dnsItem = bardata[i].aggs.dns.avg;
dnsValues.push([i, dnsItem]);
}
var connectValues = [];
for(var i=0; i<bardata.length; i++){
var connectItem = bardata[i].aggs.con.avg;
connectValues.push([i, connectItem]);
}
var SSLValues = [];
for(var i=0; i<bardata.length; i++){
var SSLItem = bardata[i].aggs.ssl.avg;
SSLValues.push([i, SSLItem]);
}
var sendValues = [];
for(var i=0; i<bardata.length; i++){
var sendItem = bardata[i].aggs.snd.avg;
sendValues.push([i, sendItem]);
}
var serverBusyValues = [];
for(var i=0; i<bardata.length; i++){
var serverBusyItem = bardata[i].aggs.srvbsy.avg;
serverBusyValues.push([i, serverBusyItem]);
}
var receiveValues = [];
for(var i=0; i<bardata.length; i++){
var receiveItem = bardata[i].aggs.rcv.avg;
receiveValues.push([i, receiveItem]);
}
pagestatsObject = [
{"key" : "DNS", "values" : dnsValues},
{"key" : "Connect", "values" : connectValues},
{"key" : "SSL", "values" : SSLValues},
{"key" : "Send", "values" : sendValues},
{"key" : "Server Busy", "values" : serverBusyValues},
{"key" : "Receive", "values" : receiveValues}
];
It's not the prettiest solution but it works for what I needed it for.

How to select object in muti level array

I am attempting to get just the smiling array under tags then attributes. I have tried both to search and simply select. Every attempt results in an undefined variable. If you could explain how to select the smiling array that would be excellent!
{
"status": "success",
"photos": [{
"url": "http://tinyurl.com/673cksr",
"pid": "F#019cbdb135cff0880096136c4a0b9bad_3547b9aba738e",
"width": 375,
"height": 406,
"tags": [{
"uids": [],
"label": null,
"confirmed": false,
"manual": false,
"width": 30.67,
"height": 28.33,
"yaw": -16,
"roll": -1,
"pitch": 0,
"attributes": {
"face": {
"value": "true",
"confidence": 84
},
"smiling": {
"value": "false",
"confidence": 46
}
},
"points": null,
"similarities": null,
"tid": "TEMP_F#019cbdb135cff0880096136c00d500a7_3547b9aba738e_56.80_41.13_0_1",
"recognizable": true,
"center": {
"x": 56.8,
"y": 41.13
},
"eye_left": {
"x": 66.67,
"y": 35.71,
"confidence": 51,
"id": 449
},
"eye_right": {
"x": 50.67,
"y": 35.47,
"confidence": 57,
"id": 450
},
"mouth_center": {
"x": 60.8,
"y": 51.23,
"confidence": 53,
"id": 615
},
"nose": {
"x": 62.4,
"y": 42.61,
"confidence": 54,
"id": 403
}
}]
}],
"usage": {
"used": 21,
"remaining": 79,
"limit": 100,
"reset_time": 1390111833,
"reset_time_text": "Sun, 19 January 2014 06:10:33 +0000"
},
"operation_id": "edc2f994cd8c4f45b3bc5632fdb27824"
}
This particular code, will aggregate all the smiling attribute from the given object and return that as an Array.
map function will get smiling attribute from each and every tag
concat function will flatten all the attributes and returns a single array per photo.
reduce function will gather all the attributes all the photos and accumulate the result in result and that will be returned at the end.
var result = data.photos.reduce(function(result, currentPhoto) {
return result.concat(currentPhoto.tags.map(function(currentTag) {
return currentTag.attributes.smiling;
}));
}, []);
console.log(result);
Output
[ { value: 'false', confidence: 46 } ]
JSON.parse(json).photos[0].tags[0].attributes.smiling
obj.photos[0].tags[0].attributes.smiling
The best way would be to loop through the tags, instead of hardcoding 0 in there
obj.photos.forEach(function(photo){
photo.tags.forEach(function(tag){
tag.attributes.smiling; // here it is
});
});
It's a bit tricky since your JSON object is a mixture of objects and arrays, but here's how you would get to the "smiling" object (it's an object since there's no associative arrays in JavaScript):
var smiling_object = obj["photos"][0]["tags"][0]["attributes"]["smiling"];
Then you if you want to do something with it:
var some_var = smiling_object["value"];
var some_other_var = smiling_object["confidence"];
alert("The combined string is " + some_var + " and " + some_other_var);

Categories