I have an array as below
array1 = [{"month":"January","location":"CENTRAL","percentage":94},
{"month":"February","location":"CENTRAL","percentage":97},
{"month":"March","location":"CENTRAL","percentage":93},
{"month":"January","location":"NORTH","percentage":95},
{"month":"February","location":"NORTH","percentage":91},
{"month":"March","location":"NORTH","percentage":98}];
I want to format my array to look as below
array2= [{
location: "CENTRAL",
January: 94,
February: 97,
March: 93},
{
location: "NORTH",
January: 95,
February: 91,
March: 98}];
I tried to use group by function as below
function groupBy(list, keyGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
if (!map.has(key)) {
map.set(key, [item]);
} else {
map.get(key).push(item);
}
});
return map;
}
const grouped = groupBy(array1, arr => arr.location);
console.log(grouped);
but I am not getting the same format. Any suggestions please what I am missing in my idea ? Thank you very much.
You can indeed use a map keyed by location, but then with plain objects as values. The problem in your code is that you push items into an array, and don't turn the month values into properties of a singular object (per location).
So given a map with plain objects, iterate the input and inject the month properties into those plain objects, with corresponding percentage values, and then take the values of that map:
const array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}];
const map = new Map(array1.map(({location}) => [location, { location }]));
array1.forEach(o => map.get(o.location)[o.month] = o.percentage);
const result = [...map.values()];
console.log(result);
You could use a dynamic approach by handing over the group key, the keys for key and value for collecting.
Then add all key/value pairs to the object and later return the values of the map.
function groupBy(list, group, key, value) {
return Array.from(list
.reduce((map, object) => map.set(object[group], Object.assign(
map.get(object[group]) || { [group]: object[group] },
{ [object[key]]: object[value] }
)), new Map)
.values()
);
}
var array = [{ month: "January", location: "CENTRAL", percentage: 94 }, { month: "February", location: "CENTRAL", percentage: 97 }, { month: "March", location: "CENTRAL", percentage: 93 }, { month: "January", location: "NORTH", percentage: 95 }, { month: "February", location: "NORTH", percentage: 91 }, { month: "March", location: "NORTH", percentage: 98 }],
result = groupBy(array, 'location', 'month', 'percentage');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
An alternative is using the function reduce
to group by location
and the function Object.values
to extract the grouped objects.
let array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}],
groupBy = (array, keygetter) => {
return Object.values(array1.reduce((a, {month, percentage, ...rest}) => {
let key = keygetter(rest);
(a[key] || (a[key] = {location: key}))[month] = percentage;
return a;
}, Object.create(null)));
},
result = groupBy(array1, (o) => o.location);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With