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.
Related
I'm trying to compare this array of object :
"platforms": [
{
"id": 1,
"name": "KF",
"bankAccounts": [
{
"id": 22,
"balance": -100,
"lendingPlatformId": 3
},
{
"id": 27,
"balance": 500,
"lendingPlatformId": 4
}
],
},
{
"id": 3,
"name": "CC",
"bankAccounts": [
{
"id": 23,
"balance": 100,
"lendingPlatformId": 1
}
],
},
{
"id": 4,
"name": "DD",
"bankAccounts": [
{
"id": 28,
"balance": 0,
"lendingPlatformId": 1
}
],
}
]
I want to compare the platform[].id and match bankAccounts[].lendingPlatformId
for example:
bankAccounts[].id = 22, its lendingPlatformId = 3, so it need to find platform[].id = 3 and bankAccounts[].id = 23 and lendingPlatformId = 1 ,then compare their balance's sum is equal to zero, than push to new array.
expecting result is one new array:
isEqualToZero = [true, false, true, false]
(order is matter)
I'm thinking make it new object like:
platofmrId = 1 :{ lendingPlatformId: 3, balance:100 }, {lendingPlatformId: 4, balance:500 }
platofmrId = 3 :{ lendingPlatformId: 1, balance:-100 }
but seems it can't achieve what i want
i've no idea how to do it...
please help, Thanks!
const res=[] //to save result
platforms.forEach(platform=>{ //go through platforms
platform.bankAccounts.forEach(bank=>{ //go through platform bank account
// to get lendingPlatform
const lendPlatform=platforms.find(p=>p.id==bank.lendingPlatformId);
//add the balance and compare
if((lendPlatform.bankAccounts[0].balance+bank.balance)==0)
res.push(true) // if combined balance is zero
else
res.push(false)
})})
console.log(res)
const platforms = [
{
"id": 1,
"name": "KF",
"bankAccounts": [
{
"id": 22,
"balance": -100,
"lendingPlatformId": 3
},
{
"id": 27,
"balance": 500,
"lendingPlatformId": 4
}
]
},
{
"id": 3,
"name": "CC",
"bankAccounts": [
{
"id": 23,
"balance": 100,
"lendingPlatformId": 1
}
]
},
{
"id": 4,
"name": "DD",
"bankAccounts": [
{
"id": 28,
"balance": 0,
"lendingPlatformId": 1
}
]
}
];
const emptyArrayInit = Array.from(new Array(4), ()=>[0,0,0,0])
platforms.forEach(platform=>{
const {id, bankAccounts}=platform;
const index = id-1;
bankAccounts.forEach(bankAccount=>{
const {balance,lendingPlatformId } =bankAccount;
const lendingPlatformIdIndex = lendingPlatformId-1;
if(balance>0){
emptyArrayInit[index][lendingPlatformIdIndex] += balance;
}else{
emptyArrayInit[lendingPlatformIdIndex][index] += balance
}
})
})
console.log(emptyArrayInit,'emptyArrayInit');
/// [ [ 0, 0, 0, 500 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ] ]
it's simple to reach your goal.
const res=[] //to save result
platforms.map(platform=>{ //first loop
platform.bankAccounts.map(bank=>{ // inner loop bankaccounts
// to get lendingPlatforms
const lendPlatforms=platforms.find(p=>p.id==bank.lendingPlatformId);
//compare balance
if((lendPlatforms.bankAccounts[0].balance+bank.balance)==0)
res.push(true) // if combined balance is equal to zero
else
res.push(false)
})})
console.log(res)
What I want is to find an object in a nested array, and to get it by a pre-known ScheduleId number, and where the Duration property is defined.
We need to find this element which is contained inside of array of "Columns", and "Columns" are contained within "Table" elements.
After finding this object, I want to update ScheduleId = 0 and Duration = 0.
Sample data:
var data = {
"Headers": [
"A",
"B",
"C",
"D"
],
"Table": [
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 12,
},
],
},
{
"Columns": [
{
"Duration": 22,
"ScheduleId": 44,
},
],
},
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 1648,
},
],
},
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 22,
},
],
},
]
};
Pseudo code:
var requestedScheduleId = 22;
var requestedObj = data.Table.find(x => requestedScheduleId.Equals(x.Columns.ScheduleId) )
requestedObj.ScheduleId = 0;
requestedScheduleId.Duration = 0;
Unsuccessful attempt:
var test = data.Table.map(({ Columns }) => {return Columns = Columns.filter(({ ScheduleId }) => ScheduleId == 22 )});
console.log(test);
I would not use .map or .filter for this. It's a plain and simple nested loop: For each table, for each column, if condition is met, do something.
Either with for loops:
for (table of data.Table) {
for (column of table.Columns) {
if (column.ScheduleId === 22) {
column.ScheduleId = 0;
column.Duration = 0;
}
}
}
or with Array#forEach:
data.Table.forEach(table => {
table.Columns.forEach(column => {
if (column.ScheduleId === 22) {
column.ScheduleId = 0;
column.Duration = 0;
}
});
});
var data = {
"Headers": [
"A",
"B",
"C",
"D"
],
"Table": [
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 12,
},
],
},
{
"Columns": [
{
"Duration": 22,
"ScheduleId": 44,
},
],
},
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 1648,
},
],
},
{
"Columns": [
{
"Duration": 0,
"ScheduleId": 22,
},
],
},
]
};
var requestedScheduleId = 22;
data.Table.forEach(table => {
table.Columns.forEach(column => {
if (column.ScheduleId === requestedScheduleId) {
column.ScheduleId = 0;
column.Duration = 0;
}
});
});
console.log(data);
In this array children array can have more childrens. I have a method in which I will get "lowValue" and "highValue". "Id" will be unique. when my method get called I need to use this unique id and replace old values of "lowValue" and "highValue" with the new ones. How can I do that?
// put your code here
<script>
myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
</script>
Simple
const data = your_original_data
function replacer(lowValue, highValue, id){
for(let i = 0; i < data.length; i++){
for(let j = 0; j < data[i].children.length; j++){
if(data[i].children[j].data.id === id){
data[i].children[j].data.lowValue = lowValue
data[i].children[j].data.highValue = highValue
return
}
}
}
}
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
const indexMap = new Map()
const parseDataToMap = (data = []) => {
data.forEach(e => {
if (e.children) {
e.children.forEach(e => {
indexMap.set(e.data.id, e.data)
})
}
})
}
parseDataToMap(myData)
console.log(myData[0].children[0].data)
const o = indexMap.get(1)
o.highValue = 25
o.lowValue = 11
console.log(myData[0].children[0].data)
Given the below-mentioned assumptions:
All children where id matches the supplied value will have the lowValue and highValue replaced.
The supplied id will always be present in the myData array in one or more children.
the following is one possible solution to achieve the desired result:
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => (
arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], [])
);
Explanation / Approach
The outer .reduce helps to iterate through the myData array
Each element in this array is placed as-is (using the ... spread operator)
Next, the children prop of each myData element is specified
Within this, i.children array is iterated using map to access each element
Each element here (again) is placed as-is using the ... spread-operator
Next, data is specified
Values for the data object are also spread (as before)
Then, if the data.id matches the parameter id then, lowValue and highValue are updated (using parameters lv and hv, respectively)
The ...( some_condition ? {k: v} : {} ) is one way to update an object's specific prop/s only when some_condition is true
Please use comments below to ask for further clarification/s.
Code Snippet
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
];
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], []);
console.log('replace id: 5, low: 5, high: 50', replaceValues());
console.log('replace id: 1, low: 11, high: 21', replaceValues(1, 11, 21));
If I have an array of objects and there are certain objects that have the same name/property (in my case there are 2 instances of objects with a name of "highway"), how can I remove these objects from the array and add a new object with that contains data from both?
const data = [
{ "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
{ "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
{ "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
{ "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
{ "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
{ "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
{ "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];
e.g. having one instance of "highway" with a data object containing the values from both:
{ "data": [ { "x": "road_type", "y": [ 0, 14 ] }, { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" }
So far I've tried to make a new empty object and loop over the data array, accumulating that empty object with names and values from that array. I was planning on converting that object to an array in the end. The code I've used is below:
const myData = {};
atts.forEach(att => {
if (myData[att.name]) {
myData[att.name].push(att.data)
} else {
myData[att.name] = att.data;
}
})
console.log(myData)
However, the code I've used above involves some additional manipulation to make the data ready for consumption by a library and I was wondering if there are simpler ways to achieve my goal?
Your solution has a decent start. There are only 2 problems with your solution:
You need to "unwrap" the array when pushing it
You need to combine them all together at the end
const myData = {};
atts.forEach(att => {
if (myData[att.name]) {
myData[att.name].push(...att.data) // Notice this change
} else {
myData[att.name] = att.data;
// or if you don't want to alter the original data
myData[att.name] = [...att.data]; // basically a shallow copy
}
})
const result = [];
for (const key in myData) {
result.push({ data: myData[key], name: key });
}
console.log(result);
You can use .reduce() (to convert your array into an aggregated value) along with .findIndex() (this helps in finding if data from same category exists in the new array you are making)
const atts = [
{ "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
{ "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
{ "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
{ "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
{ "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
{ "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
{ "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];
let myData = atts.reduce((agg, x) => {
let isIndex = agg.findIndex(a => a.name == x.name);
if(isIndex > -1) agg[isIndex].data.push(x.data[0]);
else {
agg.push({data : x.data , name : x.name});
}
return agg;
},[]);
console.log(myData)
A different approach using reduce - tracking the items by keys and merging the arrays of duplicate objects
const combined = Object.entries(data.reduce((b,a) => {
// our result will be an object so wrap it in Object.entries so we can iterate through to finish
if (b.hasOwnProperty(a.name)) b[a.name].data = [...b[a.name].data, ...a.data];
// if the property exists, merge the 'y' array
else b[a.name]=a;
// otherwise add to the object
return b;
},{})).map(e => e[1])
// finally map the result out to the desired format
const data = [
{ "data": [ { "x": "sensor_error_code", "y": [ 0, 9 ] } ], "name": 123 },
{ "data": [ { "x": "road_type", "y": [ 15, 24 ] } ], "name": "city" },
{ "data": [ { "x": "road_type", "y": [ 0, 14 ] } ], "name": "highway" },
{ "data": [ { "x": "road_type", "y": [ 25, 30 ] } ], "name": "highway" },
{ "data": [ { "x": "weather", "y": [ 0, 8 ] } ], "name": "rain" },
{ "data": [ { "x": "weather", "y": [ 9, 24 ] } ], "name": "sun" },
{ "data": [ { "x": "special_object", "y": [ 5, 15 ] } ], "name": true }
];
const combined = Object.entries(data.reduce((b,a) => {
if (b.hasOwnProperty(a.name)) b[a.name].data[0].y = [...b[a.name].data[0].y, ...a.data[0].y];
else b[a.name]=a;
return b;
},{})).map(e => e[1])
console.log(combined)
I have two JSON arrays with same fields as follows:
var total_90 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 90, "tip": 1, "type": "tab" },
{ "date": "2012-11-14T16:30:43Z", "quantity": 3, "total": 90, "tip": 0, "type": "tab" }
];
var tip_0 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 80, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 70, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:58:03Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:30:43Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" }
];
I need a third JSON file which has the intersection of the above two JSON files. (By intersection, I mean all the rows from both the JSON files which have TOTAL=90 AND TIP=0)
Is there some way to do this?
My expected output will be a third JSON file with the following output
{"date":"2012-11-14T16:30:43Z","quantity":3,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:58:03Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:30:43Z","quantity":2,"total":90,"tip":0,"type":"tab"}
You need to loop the 2 objects and merge the contents into 1 object.
For examples check this thread since this is a duplicate How can I merge properties of two JavaScript objects dynamically?
You could do the following to collect all the rows from both the JSON files which have TOTAL = 90 and TIP = 0 -
var total_90 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 90, "tip": 1, "type": "tab" },
{ "date": "2012-11-14T16:30:43Z", "quantity": 3, "total": 90, "tip": 0, "type": "tab" }
];
var tip_0 = [
{ "date": "2011-11-14T17:22:59Z", "quantity": 2, "total": 80, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T17:07:21Z", "quantity": 2, "total": 70, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:58:03Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" },
{ "date": "2011-11-14T16:30:43Z", "quantity": 2, "total": 90, "tip": 0, "type": "tab" }
];
// An empty arrays to contain final intersection array
var result = [];
/* now looping over both arrays to traverse all the elements from them */
// iterating over first array
total_90.forEach(x => {
// iterating over second array
tip_0.forEach(y => {
// push into output array only if total is 90 & tip is 0
if ((x.total == 90 && y.total == 90) && (x.tip == 0 && y.tip == 0)) {
result.push({
date: x.date,
quantity: x.quantity,
total: x.total,
tip: x.tip,
type: x.type
});
}
});
});
console.log(result);
Note - this can be optimized to reduce the time complexity.
function intersection(a, b)
{
var result = [];
for (var i = 0; i < a.length; i++){
if (a[i].total == 90 && a[i].tip == 0)
{
result.push(a[i]);
}
}
for (var i = 0; i < b.length; i++){
if (b[i].total == 90 && b[i].tip == 0)
{
result.push(b[i]);
}
}
return result;
}
JSFiddle
EDIT: Update the function with the use of concat to provide a slightly more short hand.
function intersection(a, b)
{
var result = [];
var c = a.concat(b);
for (var i = 0; i < c.length; i++){
if (c[i].total == 90 && c[i].tip == 0)
{
result.push(c[i]);
}
}
return result;
}
New JSFiddle
var total_90 = [
{"date":"2011-11-14T17:22:59Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T17:07:21Z","quantity":2,"total":90,"tip":1,"type":"tab"},
{"date":"2012-11-14T16:30:43Z","quantity":3,"total":90,"tip":0,"type":"tab"}
]
var tip_0 = [
{"date":"2011-11-14T17:22:59Z","quantity":2,"total":80,"tip":0,"type":"tab"},
{"date":"2011-11-14T17:07:21Z","quantity":2,"total":70,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:58:03Z","quantity":2,"total":90,"tip":0,"type":"tab"},
{"date":"2011-11-14T16:30:43Z","quantity":2,"total":90,"tip":0,"type":"tab"}
]
allData['total_90'] = total_90;
allData['tip_0'] = tip_0;
use allData