Reputation: 9662
I have an array of objects with the following structure that is being sent as response:
let sampleData = [
{ values: { High: 4, Low: 5, Medium: 7 } , time: "1571372233234" , sum: 16 },
{ values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},
{ time: "14354545454", sum: 0},
{ time: "14354545454", sum: 0} }
];
I need to take each key within each object inside array and form an array out of it. Basically grouping based on the key present in all the objects.If the object has no "values" it should return 0 across the val1,val2,val3.
But the issue , the order of the keys "high,low,medium" inside "values" object in the question is unpredictable. With whatever code I have written keys that are present in the first object will be grouped and follows that order. But I want be it any input order, It should always give me this order "High Medium Low" Order.
The resultant array of objects should look like and should always follow "High Medium Order":
result = [
{ name: 'High', data: [4, 5, 0, 0] },
{ name: 'Medium', data: [5, 3, 0, 0] },
{ name: 'Low', data: [7, 1, 0, 0] }
]
I have tried the following:
let sampleData = [{ values: { High: 4, Low: 5, Medium: 7 } , time: "1571372233234" , sum: 16 },{ values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},{ time: "14354545454", sum: 0},{ time: "14354545454", sum: 0 }];
const keySet = new Set(sampleData.flatMap(a => Object.keys(a.values || {})));
const merged = sampleData.reduce((acc, {
values = {}
}) => {
keySet.forEach(name => {
acc[name] = acc[name] || {
name,
data: []
};
acc[name].data.push(values[name] || 0);
});
return acc;
}, {});
console.log(merged);
Upvotes: 2
Views: 64
Reputation: 386670
You could take the result set and iterate for the key and array for the value.
let sampleData = [{ values: { High: 4, Low: 5, Medium: 7 }, time: "1571372233234", sum: 16 }, { values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234", sum: 9 }, { time: "14354545454", sum: 0 }, { time: "14354545454", sum: 0 }],
keys = ['High', 'Low', 'Medium'],
grouped = sampleData.reduce((r, { values = {} } = {}) => {
r.forEach(({ name, data }) => data.push(values[name] || 0));
return r;
}, keys.map(name => ({ name, data: [] })));
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 33726
You can check for the undefined
value when the attr values
is not present.
sampleData.reduce((a, {values: {High = 0, Low = 0, Medium = 0} = {}})
^
|
+-- When attr "values" is
undefined initialize
as an "empty" object.
let sampleData = [{ values: { High: 4, Low: 5, Medium: 7 } , time: "1571372233234" , sum: 16 },{ values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},{ time: "14354545454", sum: 0},{ time: "14354545454", sum: 0}];
let result = Object.values(sampleData.reduce((a, {values: {High = 0, Low = 0, Medium = 0} = {}}) => {
(a["High"] || (a["High"] = {name: "High", data: []})).data.push(High);
(a["Low"] || (a["Low"] = {name: "Low", data: []})).data.push(Low);
(a["Medium"] || (a["Medium"] = {name: "Medium", data: []})).data.push(Medium);
return a;
}, Object.create(null)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 14191
You are returning an object and as such the order of the keys is not guaranteed. You probably want an array instead of an object.
You could just construct a final merged
object like this
mergedFinal = [ merged['High'], merged['Medium'], merged['Low'] ]
Upvotes: 0