Reputation: 738
I am trying to merge JS objects together that have the same key. In this case the key I plan to use is the "time" field, and then for each time I want to include every "app" as a key, and "sum" as its value. The other fields I do not plan to include.
I've tried a few routes but still having trouble, code below:
var data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
const result = data.reduce(function (r, e) {
return Object.keys(e).forEach(function (k) {
if (!r[k]) r[k] = [].concat(e[k])
else r[k] = r[k].concat(e[k])
}), r
}, {})
console.log(result)
This is how I want the data to output:
[
{
"time": "00:06",
"cloudmark-desktop": 2970,
"dns": 519169
},
{
"time": "01:06",
"cloudmark-desktop": 999,
"dns": 999
}
]
Any help appreciated! Thanks
Upvotes: 0
Views: 1172
Reputation: 469
One of the possible solutions:
const data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
const groupedDataByTime = data.reduce((accumulator, currentValue) => {
if (!accumulator.hasOwnProperty(currentValue.time)) {
accumulator[currentValue.time] = {};
}
const mapByTime = accumulator[currentValue.time];
if (!mapByTime.hasOwnProperty(currentValue.app)) {
mapByTime[currentValue.app] = 0;
}
mapByTime[currentValue.app] += parseInt(currentValue.sum, 10);
return accumulator;
}, {});
const result = Object.keys(groupedDataByTime).map(time => {
return Object.assign({ time }, groupedDataByTime[time]);
});
console.log(result);
Upvotes: 1
Reputation: 171
Here is another solution in pure JavaScript which is also more easy to read and understand:
var timesArray = [];
var uniqueTimesArray = [];
var result = [];
var items = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
items.forEach(function(element) {
timesArray.push(element.time);
});
uniqueTimesArray = timesArray.filter( onlyUnique );
uniqueTimesArray.forEach(function(timeElement) {
var resultItem = {};
var key = "time";
resultItem[key] = timeElement;
items.forEach(function(item) {
if(item.time == timeElement){
resultItem[item.app] = item.sum;
}
});
result.push(resultItem);
});
console.log(result);
Upvotes: 0
Reputation: 2387
You were using {}
in reduce method instead of []
. Try this snippet for the shortest method to achieve this.
var data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
const result = data.reduce(function (r, e) {
let val = r.find(({time}) => time === e.time)
if (!val) {
val = {}
r.push(val)
}
val.time = e.time;
val[e.app] = e.sum;
return r;
}, []);
console.log(result)
Upvotes: 1
Reputation: 12961
If you prefer doing it without the help of libraries like lodash you can do it like this:
var data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
const result = data.reduce((acc, value, key) => {
const object = acc.find(item => item.time === value.time);
if(object) {
if (Number.isInteger(object[value.app])) {
object[value.app] += value.sum
} else {
object[value.app] = value.sum
}
return acc;
}
acc.push({
time: value.time,
[value.app]: value.sum
});
return acc;
}, []);
console.log(result);
Upvotes: 1
Reputation: 772
const data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
const formattedData = data.reduce((acc, a) => {
const timeExists = acc.findIndex(b => a.time === b.time);
if(timeExists > -1) {
const copy = [...acc];
copy[timeExists] = {
...copy[timeExists],
[a.app]: a.sum
}
return copy
} else {
return [
...acc,
{
time: a.time,
[a.app]: a.sum
}
]
}
}, []);
console.log(formattedData);
Try this. Probably the first part of the if statement deserves some love though.
Upvotes: 1
Reputation: 1330
Here's one way, albeit a bit ugly:
var output = {};
var data = [
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 2970,
"events": "2.9KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 519169,
"events": "507.0KiB",
"time": "00:06"
},
{
"eventdate": 1561334400000,
"app": "cloudmark-desktop",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
},
{
"eventdate": 1561334400000,
"app": "dns",
"sum": 999,
"events": "507.0KiB",
"time": "01:06"
}
];
for (var i = 0; i < data.length; i++) {
var d = data[i];
if (output[d["time"]]) {
output[d["time"]][d["app"]] = d["sum"];
} else {
output[d["time"]] = {
time: d["time"],
[d["app"]]: d["sum"]
}
}
}
console.log(Object.values(output));
Upvotes: 1