Reputation: 438
I've this dataset:
const people = [
{
name: 'Pete',
gender: 'Male',
age: 22
},
{
name: 'Samantha',
gender: 'Female',
age: 20
},
{
name: 'Frank',
gender: 'Male',
age: 22
},
{
name: 'Gary',
gender: 'Male',
age: 21
},
{
name: 'Maria',
gender: 'Female',
age: 20
},
{
name: 'Hannah',
gender: 'Female',
age: 21
},
{
name: 'Pete',
gender: 'Male',
age: 20
}
];
and I wnt to group by gender
and by age
. So the result should be:
{
Male: {
'20': [ { name: 'Pete', gender: 'Male', age: 20 } ],
'21': [ { name: 'Gary', gender: 'Male', age: 21 } ],
'22': [
{ name: 'Pete', gender: 'Male', age: 22 },
{ name: 'Frank', gender: 'Male', age: 22 }
]
},
Female: {
'20': [
{ name: 'Samantha', gender: 'Female', age: 20 },
{ name: 'Maria', gender: 'Female', age: 20 }
],
'21': [ { name: 'Hannah', gender: 'Female', age: 21 } ],
'22': [ ],
}
}
You can see that the age
keys are always 20, 21, 22
even if there aren't females of 22 years old.
I try:
const groupedByMultiple = map(groupBy(dataset, 'gender'), function (obj, key) {
const temp = {}
temp[key] = groupBy(obj, 'age')
return temp
})
but the result is an array instead of an object. How can I solve?
Upvotes: 0
Views: 86
Reputation: 400
you can use array.reduce to get objects from arrays. it can return anything you want from acumulating values from an array. if the keys you want are known before it is much simpler by setting initial value.
people.reduce((accumulated, person) => {
acccumulated[person.gender][person.age].push(person);
return accumulated;
]}, {
male: {
20: [],
21: [],
22: []
},
female: {
20: [],
21: [],
22: []
},
});
if you don't know what values there are you can still do it by checking for what is there and assigning appropriately
people.reduce((accumulated, person) => {
if(acccumulated[person.gender]) {
const arr = acccumulated[person.gender][person.age] ? acccumulated[person.gender][person.age] : [];
arr.push(person)
acccumulated[person.gender][person.age] = arr;
} else {
acccumulated[person.gender] = {};
acccumulated[person.gender][person.age] = [person];
}
return accumulated;
]}, {});
Upvotes: 1
Reputation: 386570
You could take an array of keys fro the wanted groups and reduce the group for pushing the object.
const
people = [{ name: 'Pete', gender: 'Male', age: 22 }, { name: 'Samantha', gender: 'Female', age: 20 }, { name: 'Frank', gender: 'Male', age: 22 }, { name: 'Gary', gender: 'Male', age: 21 }, { name: 'Maria', gender: 'Female', age: 20 }, { name: 'Hannah', gender: 'Female', age: 21 }, { name: 'Pete', gender: 'Male', age: 20 }],
groups = ['gender', 'age'], result = people.reduce((r, o) => {
groups
.reduce((group, k, i, { length }) => group[o[k]] ??= i + 1 === length ? [] : {}, r)
.push(o);
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 69
//distinct ages
let distinctAges=[];
people.foeEach(v=>{
if(distimctAges.includes(v.age)){
distinctAges.push(v.age)
}
})
//init empty assign
let resultObj={
Male:{},
Female:{}
};
//assign data
distinctAges.foeEach(v=>{
resultObj.Male[v.age]=filter('Male',v.age);
resultObj.Female[v.age]=filter('Female',v.age);
})
//filter by gender and age
funtion filter(gender,age){
return people.filter(data=>data.age==age & data.gender==gender);
}
console.log(resultObj);
Upvotes: 0