我正在尝试根据其中一个键合并JSON数组中的一些项目。我希望按“度量”进行分组,然后我需要查看“rounded_counts”中的所有时间/值数据,如果时间相同,则需要将值相加。这是源数据:
let sourceData = [
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 3 },
{ "2017-11-16 15:11:00": 5 }
]
},
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 28 },
{ "2017-11-16 15:11:00": 28 }
]
},
{
"metric": "Quarantine",
"rounded_counts": [
{ "2017-11-16 15:10:00": 1 },
{ "2017-11-16 15:11:00": 2 }
]
}
];
以下是Highcharts图表库所需的输出 - 请注意名为“已批准”的2个指标如何合并其值
可以使用下划线和/或ES6 - 提前致谢!
let chartData = [
{
"name": "Approved",
"data": [
[ "2017-11-16 15:10:00", 30 ],
[ "2017-11-16 15:11:00", 33 ]
]
},
{
"name": "Quarantine",
"data": [
[ "2017-11-16 15:10:00", 1 ],
[ "2017-11-16 15:11:00", 2 ]
]
}
]
答案 0 :(得分:2)
这是我的两分钱。
const sourceData = [
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 3 },
{ "2017-11-16 15:11:00": 5 }
]
},
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 28 },
{ "2017-11-16 15:11:00": 28 }
]
},
{
"metric": "Quarantine",
"rounded_counts": [
{ "2017-11-16 15:10:00": 1 },
{ "2017-11-16 15:11:00": 2 }
]
}
];
function mergeDatas(currentObject, rounded_counts) {
return rounded_counts.map(x => {
if (currentObject.data.some(y => y[0] === Object.keys(x)[0])) {
const miniArray = currentObject.data.find(y =>
y[0] === Object.keys(x)[0]);
miniArray[1] += x[Object.keys(x)[0]];
return miniArray;
}
return x;
})
}
const result = sourceData.reduce((tmp, x) => {
if (tmp.some(t => t.name === x.metric)) {
const currentObject = tmp.find(y => y.name === x.metric);
mergeDatas(currentObject, x.rounded_counts);
return tmp;
}
tmp.push({
name: x.metric,
data: x.rounded_counts.map(y => {
const key = Object.keys(y)[0];
return [key, y[key]];
}),
});
return tmp;
}, []);
console.log(result);
答案 1 :(得分:1)
看看这样的事情:
[{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 3 },
{ "2017-11-16 15:11:00": 5 }
]
},
...
].reduce((tmp, x) => {
const ptr = tmp;
// look if it exist
const index = ptr.findIndex(y => y.name === x.metric);
// It exist
if (index !== -1) {
ptr[index].data = addSimilarDatesValues([
...ptr[index].data,
...x.rounded_counts,
]);
return ptr;
}
// it doesn't
ptr.push({
name: x.metric,
data: x.rounded_counts.map(y => [
Object.keys(y)[0],
y[Object.keys(y)[0]],
]),
});
return ptr;
}, []);
/**
* We have this in entry
*
* [
* { "2017-11-16 15:10:00": 3 },
* { "2017-11-16 15:11:00": 5 },
* { "2017-11-16 15:10:00": 28 },
* { "2017-11-16 15:11:00": 28 },
* ]
*
* Or this
*
* [
* [ "2017-11-16 15:10:00", 3 ],
* [ "2017-11-16 15:11:00", 5 ],
* ]
*
*
* WARNING: Here you can have already converted data
* It happens when we push the first item into the list
*
* We return this
*
* [
* [ "2017-11-16 15:10:00", 31 ],
* [ "2017-11-16 15:11:00", 33 ],
* ]
*
*/
const addSimilarDatesValues = (array) => {
return array.reduce((tmp, x) => {
const ptr = tmp;
// Handle the already converted data
const isArray = x instanceof Array;
const keyToStore = isArray ? x[0] : Object.keys(x)[0];
const valueToStore = isArray ? x[1] : x[Object.keys(x)[0]];
// Look if there is a date already in tmp
const index = ptr.findIndex(y => y[0] === keyToStore);
// It's not
if (index === -1) {
// add a new entry for the date
return [
...ptr,
[
keyToStore,
valueToStore,
],
];
}
// It is - add the value into the already stored one
ptr[index][1] += valueToStore;
return ptr;
}, []);
};
const addSimilarDatesValues = (array) => {
return array.reduce((tmp, x) => {
const ptr = tmp;
const isArray = x instanceof Array;
const keyToStore = isArray ? x[0] : Object.keys(x)[0];
const valueToStore = isArray ? x[1] : x[Object.keys(x)[0]];
// Look if there is a date already in tmp
const index = ptr.findIndex(y => y[0] === keyToStore);
// It's not
if (index === -1) {
// add a new entry for the date
return [
...ptr, [
keyToStore,
valueToStore,
],
];
}
// It is - add the value into the already stored one
ptr[index][1] += valueToStore;
return ptr;
}, []);
};
const ret = [{
"metric": "Approved",
"rounded_counts": [{
"2017-11-16 15:10:00": 3
},
{
"2017-11-16 15:11:00": 5
},
]
},
{
"metric": "Approved",
"rounded_counts": [{
"2017-11-16 15:10:00": 28
},
{
"2017-11-16 15:11:00": 28
},
]
},
{
"metric": "Quarantine",
"rounded_counts": [{
"2017-11-16 15:10:00": 1
},
{
"2017-11-16 15:11:00": 2
},
]
}
].reduce((tmp, x) => {
const ptr = tmp;
// look if it exist
const index = ptr.findIndex(y => y.name === x.metric);
// It exist
if (index !== -1) {
ptr[index].data = addSimilarDatesValues([
...ptr[index].data,
...x.rounded_counts,
]);
return ptr;
}
// it doesn't
ptr.push({
name: x.metric,
data: x.rounded_counts.map(y => [
Object.keys(y)[0],
y[Object.keys(y)[0]],
]),
});
return ptr;
}, []);
console.log(ret);
答案 2 :(得分:0)
尽管@Grégory的答案相当优雅,但它并没有输出正确的表格。 function
包含一个键/值对象,而不是包含1个键和1个值的2个元素的数组。
请改为尝试:
data
答案 3 :(得分:0)
由于数据结构的原因,您似乎需要使用一些嵌套循环和比较。我不认为你可以用javascript中的内置数组函数来做到这一点。试试这个:
let sourceData = [{
"metric": "Approved",
"rounded_counts": [{
"2017-11-16 15:10:00": 3
}, {
"2017-11-16 15:11:00": 5
}]
}, {
"metric": "Approved",
"rounded_counts": [{
"2017-11-16 15:10:00": 28
}, {
"2017-11-16 15:11:00": 28
}]
}, {
"metric": "Quarantine",
"rounded_counts": [{
"2017-11-16 15:10:00": 1
}, {
"2017-11-16 15:11:00": 2
}]
}];
let chartData = [];
function isSame(obj1, obj2) {
if (obj1.metric && obj1.metric == obj2.metric &&
obj1.rounded_counts && obj2.rounded_counts &&
obj1.rounded_counts.length == obj2.rounded_counts.length) {
var roundedCountsDifferent = false;
for (var i in obj1.rounded_counts) {
var count = 0;
var key1;
var key2;
for (var j in obj1.rounded_counts[i]) {
key1 = j;
break;
}
for (var j in obj2.rounded_counts[i]) {
key2 = j;
break;
}
roundedCountsDifferent = key1 != key2;
return !roundedCountsDifferent;
}
}
return false;
}
for (var i in sourceData) {
var source = sourceData[i];
var existingChart = null;
for (var j in chartData) {
if (isSame(source, chartData[j])) {
existingChart = chartData[j];
for (var k in source.rounded_counts) {
var key;
var val;
for (var kv in source.rounded_counts[k]) {
val = source.rounded_counts[k][kv];
break;
}
for (var kv in existingChart.rounded_counts[k]) {
existingChart.rounded_counts[k][kv] += val;
break;
}
}
}
}
if (!existingChart) {
chartData.push(source);
}
}
console.log(chartData);
答案 4 :(得分:-1)
我认为这就是你要找的东西。这是合并两个数据集,添加第一个不存在的第二个项目的值。
有很多评论,因此您可以在处理数据时跟进。
let sourceData = [
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 3 },
{ "2017-11-16 15:11:00": 5 }
]
},
{
"metric": "Approved",
"rounded_counts": [
{ "2017-11-16 15:10:00": 28 },
{ "2017-11-16 15:11:00": 28 },
{ "2017-11-16 15:12:00": 29 }
]
},
{
"metric": "Quarantine",
"rounded_counts": [
{ "2017-11-16 15:10:00": 1 },
{ "2017-11-16 15:11:00": 2 }
]
}
];
let chartData = []; // our combined output Dataset
// map over the sourceData one item at a time.
sourceData.map((item) => {
let d = chartData.find(data => data.metric == item.metric);
if ( d ) { // if an existing item exists
//console.log("item exists"); console.log(d);
// create a new array of the existing items
rounded_counts = d.rounded_counts;
// iterate all the rounded_counts in the current item
item.rounded_counts.map((count) => {
let key = Object.keys(count)[0]; // get the key for the current object, this would be the datetime
// console.log("key: " + key);
// check for any existing items with the same key (datetime)
let additional = rounded_counts.find(data => Object.keys(data)[0] == key);
// console.log(additional); // print the additional item raw
if (additional) {
// console.log(additional[Object.keys(additional)]); // print the additional items value, this is the value we will add to the existing item with the same "metric" and same value
let Z = (count[key] + additional[Object.keys(additional)]); // add our 2 values together
// console.log(Z); // print this new value
let newObj = {}; newObj[key] = Z; // create a new Object with the new value and existing key
rounded_counts[rounded_counts.findIndex(data => Object.keys(data)[0] == key)] = newObj; // update the existing rounded_count item with our new object
} else {
rounded_counts.push(count);
}
});
// set the exists items rounded_counts to our new array
d.rounded_counts = rounded_counts;
} else {
chartData.push(item);
}
});
// print the dataset so we can inspect the results
console.log(chartData);