Reputation: 99
I have an array with some streaming channel data, according to the shift (Morning and Afternoon).
I spent the night trying some functions like reduce, but I couldn't understand how it works and stagnated.
var array = [{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"55.00"},{"Outro":"20.00"}]},{"label":"manha","data":[{"Amazon Prime":"50.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"25.00"},{"Outro":"0.00"}]},{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"50.00"},{"Outro":"0.00"}]},{"label":"tarde","data":[{"Amazon Prime":"10.00"},{"AppleTV":"11.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"9.00"},{"Outro":"20.00"}]},{"label":"tarde","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"5.00"},{"Nenhuma":"25.00"},{"Netflix":"20.00"},{"Outro":"50.00"}]}]
I expect to have this output:
The sum total of all streaming channels, divided by the amount of objects value per shift (morning and afternoon)
[{"label":"manha","data":[{"Amazon Prime":"16.66"},{"AppleTV":"0.00"},{"HBO Max":"16.66"},{"Nenhuma":"16.66"},{"Netflix":"43.33"},{"Outro":"6.66"}]},{"label":"tarde","data":[{"Amazon Prime":"5.00"},{"AppleTV":"5.50"},{"HBO Max":"2.50"},{"Nenhuma":"36.00"},{"Netflix":"14.50"},{"Outro":"35.00"}]}]
I would be very grateful if you could help me, and if possible, explain.
Upvotes: 1
Views: 89
Reputation: 4780
Another approach. I simply used hash grouping twice to create an intermediate object and create a final object at the end
const data = [{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"55.00"},{"Outro":"20.00"}]},{"label":"manha","data":[{"Amazon Prime":"50.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"25.00"},{"Outro":"0.00"}]},{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"50.00"},{"Outro":"0.00"}]},{"label":"tarde","data":[{"Amazon Prime":"10.00"},{"AppleTV":"11.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"9.00"},{"Outro":"20.00"}]},{"label":"tarde","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"5.00"},{"Nenhuma":"25.00"},{"Netflix":"20.00"},{"Outro":"50.00"}]}]
const groups = data.reduce((acc, { label, data }) => {
acc[label] ??= {};
data.forEach((item) => {
const [[channel, value]] = Object.entries(item);
acc[label][channel] ??= [];
acc[label][channel].push(Number(value));
});
return acc;
}, {});
// groups
//
// {"manha": {
// "Amazon Prime": [0, 50, 0"],
// "AppleTV": [0, 0, 0],
// "HBO Max": [25, 25, 0],
// "Nenhuma": [0, 0, 50],
// "Netflix": [55, 25,50],
// "Outro": [20, 0, 0]},
// ...}
const getFixedAvg = (data) => {
const average = data.reduce((avg, e) => avg + e) / data.length;
return (Math.floor(average * 100) / 100) // fix 16.67 to 16.66
.toFixed(2);
};
const makeData = (dataObj) => Object.entries(dataObj)
.map(([channel, dataValues]) => ({ [channel]: getFixedAvg(dataValues) }));
const result = Object.entries(groups)
.map(([label, dataObj]) => ({ label, data: makeData(dataObj) }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Upvotes: 1
Reputation: 25956
Let's solve this problem in steps.
The first attempt is using reduce
to iterate through the result and build something.
For simplicity let's get it to build an object where the keys
represents the labels.
The reason for this is we can use this key
to merge similar keys together.
On the TODO we observe that:
let array = [{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"55.00"},{"Outro":"20.00"}]},{"label":"manha","data":[{"Amazon Prime":"50.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"25.00"},{"Outro":"0.00"}]},{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"50.00"},{"Outro":"0.00"}]},{"label":"tarde","data":[{"Amazon Prime":"10.00"},{"AppleTV":"11.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"9.00"},{"Outro":"20.00"}]},{"label":"tarde","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"5.00"},{"Nenhuma":"25.00"},{"Netflix":"20.00"},{"Outro":"50.00"}]}];
let result = array.reduce( function (p, c, i, a) {
let label = c.label;
if (!(label in p)) {
p[label] = c.data;
}
return p;
}, { } );
console.log(JSON.stringify(result, undefined, 2));
// Output:
// {
// "manha": [ { "Amazon Prime": "0.00" },
// { "AppleTV": "0.00" },
// { "HBO Max": "25.00" },
// { "Nenhuma": "0.00" },
// { "Netflix": "55.00" },
// { "Outro": "20.00" }
// ],
// "tarde": [ { "Amazon Prime": "10.00" },
// { "AppleTV": "11.00" },
// { "HBO Max": "0.00" },
// { "Nenhuma": "50.00" },
// { "Netflix": "9.00" },
// { "Outro": "20.00" }
// ]
// }
For the second attempt, we will:
in
to determine whether a key exists or notlet array = [{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"55.00"},{"Outro":"20.00"}]},{"label":"manha","data":[{"Amazon Prime":"50.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"25.00"},{"Outro":"0.00"}]},{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"50.00"},{"Outro":"0.00"}]},{"label":"tarde","data":[{"Amazon Prime":"10.00"},{"AppleTV":"11.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"9.00"},{"Outro":"20.00"}]},{"label":"tarde","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"5.00"},{"Nenhuma":"25.00"},{"Netflix":"20.00"},{"Outro":"50.00"}]}];
let result = array.reduce( function (p, c, i, a) {
let label = c.label;
if (!(label in p)) {
p[label] = { };
}
for (let i = 0; i < c.data.length; i++) {
let e = Object.entries(c.data[i]);
let k = e[0][0];
let v = parseFloat(e[0][1]);
if (!(k in p[label])) {
p[label][k] = [ ];
}
p[label][k].push(v);
}
return p;
}, { } );
console.log(JSON.stringify(result, undefined, 2));
// Output:
// {
// "manha": {
// "Amazon Prime": [ 0, 50, 0 ],
// "AppleTV": [ 0, 0, 0 ],
// "HBO Max": [ 25, 25, 0 ],
// "Nenhuma": [ 0, 0, 50 ],
// "Netflix": [ 55, 25, 50 ],
// "Outro": [ 20, 0, 0 ]
// },
// "tarde": {
// "Amazon Prime": [ 10, 0 ],
// "AppleTV": [ 11, 0 ],
// "HBO Max": [ 0, 5 ],
// "Nenhuma": [ 50, 25 ],
// "Netflix": [ 9, 20 ],
// "Outro": [ 20, 50 ]
// }
// }
For the final step, we just average out the remaining array and convert the numerical result back to a string.
let array = [{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"55.00"},{"Outro":"20.00"}]},{"label":"manha","data":[{"Amazon Prime":"50.00"},{"AppleTV":"0.00"},{"HBO Max":"25.00"},{"Nenhuma":"0.00"},{"Netflix":"25.00"},{"Outro":"0.00"}]},{"label":"manha","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"50.00"},{"Outro":"0.00"}]},{"label":"tarde","data":[{"Amazon Prime":"10.00"},{"AppleTV":"11.00"},{"HBO Max":"0.00"},{"Nenhuma":"50.00"},{"Netflix":"9.00"},{"Outro":"20.00"}]},{"label":"tarde","data":[{"Amazon Prime":"0.00"},{"AppleTV":"0.00"},{"HBO Max":"5.00"},{"Nenhuma":"25.00"},{"Netflix":"20.00"},{"Outro":"50.00"}]}];
let tmp = array.reduce( function (p, c, i, a) {
let label = c.label;
if (!(label in p)) {
p[label] = { };
}
for (let i = 0; i < c.data.length; i++) {
let e = Object.entries(c.data[i]);
let k = e[0][0];
let v = parseFloat(e[0][1]);
if (!(k in p[label])) {
p[label][k] = [ ];
}
p[label][k].push(v);
}
return p;
}, { } );
let result = Object.entries(tmp).map( ( [label, _data] ) => (
{ label : label,
data: Object.entries(_data).map( function ( [k, v] ) {
let obj = { };
obj[k] = ( v.reduce( (p,c) => p + c ) / v.length ).toFixed(2);
return obj;
} )
}
) );
console.log(JSON.stringify(result, undefined, 2));
// Output:
// [
// {
// "label": "manha",
// "data": [
// { "Amazon Prime": "16.67" },
// { "AppleTV": "0.00" },
// { "HBO Max": "16.67" },
// { "Nenhuma": "16.67" },
// { "Netflix": "43.33" },
// { "Outro": "6.67" }
// ]
// },
// {
// "label": "tarde",
// "data": [
// { "Amazon Prime": "5.00" },
// { "AppleTV": "5.50" },
// { "HBO Max": "2.50" },
// { "Nenhuma": "37.50" },
// { "Netflix": "14.50" },
// { "Outro": "35.00" }
// ]
// }
// ]
Some final remarks on this answer compared to the question supplied.
toFixed(2)
which implements a round up
"16.67"
instead of "16.66"
for the "manha" averages"37.50"
( i.e. (50 + 25) / 2 === 37.50
) instead of "36.00"
Upvotes: 1
Reputation: 11
This is probably a bit longer then what you have hoped for but it should work.
let newAr = []
for(el of array) {
const currentLabel = el.label
let indexOfLabel = -1
for(let i = 0; i < newAr.length; ++i) {
if(newAr[i].label === currentLabel) indexOfLabel = i
}
if(indexOfLabel >= 0) {
for(let i = 0; i < el.data.length; ++i) {
const key = Object.keys(el.data[i])
newAr[indexOfLabel].data[i][key] = parseInt(newAr[indexOfLabel].data[i][key])
newAr[indexOfLabel].data[i][key] += parseInt(el.data[i][key])
}
} else {
newAr.push(el)
}
}
const occurrences = array.reduce(function (acc, curr) {
return acc[curr.label] ? ++acc[curr.label] : acc[curr.label] = 1, acc
}, {});
for(el of newAr) {
for(data of el.data) {
data[Object.keys(data)] = (data[Object.keys(data)] / occurrences[el.label]).toFixed(2)
}
}
Upvotes: 1