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.
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.
Share Improve this question asked Feb 24, 2019 at 21:49 DevTNDevTN 5932 gold badges13 silver badges37 bronze badges 3 |6 Answers
Reset to default 3You 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; }
One approach is to use .filter()
and .map()
var 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 groupBy = (arr, prop, propName1, propName2, propName3) =>
Object.assign({[prop]:propName1}
, ...arr.filter(({[prop]:p}) => p === propName1)
.map(({[propName2]:m, [propName3]:p}) => ({[m]: p}))
);
const locations = ["CENTRAL", "NORTH"];
let res = locations.map(prop => groupBy(array1, "location", prop, "month", "percentage"));
console.log(res);
The problem is, you can't just rearrange the properties in an object. According to the ECMAScript specifications:
An ECMAScript object is an
unordered
collection of properties
You can rearrange the properties using your function, but the order will not be guaranteed in the final object.
Here is another example using reduce, pass the callback function and specify the key in it
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
}
];
function groupBy(list, callback) {
return list.reduce((acc, x) => {
const key = callback(x);
if (!acc[key]) {
return {
...acc,
[key]: [x]
}
}
return {
...acc,
[key]: [...acc[key], x]
}
}, {})
}
// callback function
function locationName(obj) {
return obj.location
}
console.log('group by location name:', groupBy(array1, locationName));
Map
is not anArray
– guest271314 Commented Feb 24, 2019 at 21:54