I have an array of objects which presents tasks. These tasks are categorized (primary / secondary category).
let tasks = [
{
id: 1,
name: 'Cleanup desk',
primary_category: {
id: 1,
name: 'Indoor'
},
secondary_category: {
id: 2,
name: 'Surfaces'
}
},
{
id: 2,
name: 'Cleanup office floors',
primary_category: {
id: 1,
name: 'Indoor'
},
secondary_category: {
id: 3,
name: 'Ground'
}
},
{
id: 3,
name: 'Water plants',
primary_category: {
id: 2,
name: 'Outdoor'
},
secondary_category: {
id: 3,
name: 'Irrigation'
}
}
];
I now try to create a categories accordion in my frontend and therefore need to group my array differently. The structure should look like:
1) primary category
> secondary category
> tasks
> secondary category
> tasks
2) primary category
> secondary category
> tasks
Therefore I'm trying to achieve a structure similar to this:
let tasks_categorized = [
{
id: 1,
name: 'Indoor',
secondary_categories: [
{
id: 2,
name: 'Surfaces',
tasks: [
{
id: 1,
name: 'Cleanup desk'
}
]
},
{
id: 3,
name: 'Ground',
tasks: [
{
id: 2,
name: 'Cleanup office floors'
}
]
}
]
},
{
id: 2,
name: 'Outdoor',
secondary_categories: [
{
id: 3,
name: 'Irrigation',
tasks: [
{
id: 3,
name: 'Water plants'
}
]
}
]
}
];
I tried using groupBy
by lodash but this does not allow grouping by multiple nested key-value pairs. Does anybody know an approach to solve this?
Thank you in advance!
CodePudding user response:
You could take a dynamic approach with an array of grouping data and keys for the nested arrays.
const
tasks = [{ id: 1, name: 'Cleanup desk', primary_category: { id: 1, name: 'Indoor' }, secondary_category: { id: 2, name: 'Surfaces' } }, { id: 2, name: 'Cleanup office floors', primary_category: { id: 1, name: 'Indoor' }, secondary_category: { id: 3, name: 'Ground' } }, { id: 3, name: 'Water plants', primary_category: { id: 2, name: 'Outdoor' }, secondary_category: { id: 3, name: 'Irrigation' } }],
groups = [
[o => o, 'primary category'],
[o => o.primary_category, 'secondary category'],
[o => o.secondary_category, 'tasks']
],
result = tasks.reduce((r, o) => {
groups.reduce((parent, [fn, children]) => {
const { id, name } = fn(o);
let item = (parent[children] ??= []).find(q => q.id === id)
if (!item) parent[children].push(item = { id, name });
return item;
}, r);
return r;
}, {})[groups[0][1]];
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
might not be the cleanest solution, but this will work
const tasks = [{
id: 1,
name: "Cleanup desk",
primary_category: {
id: 1,
name: "Indoor"
},
secondary_category: {
id: 2,
name: "Surfaces"
}
},
{
id: 2,
name: "Cleanup office floors",
primary_category: {
id: 1,
name: "Indoor"
},
secondary_category: {
id: 3,
name: "Ground"
}
},
{
id: 3,
name: "Water plants",
primary_category: {
id: 2,
name: "Outdoor"
},
secondary_category: {
id: 3,
name: "Irrigation"
}
}
];
let fixedCategories = [];
tasks.map((object) => {
const categoryIndex = fixedCategories.findIndex(
(category) => category.name === object.primary_category.name
);
if (categoryIndex >= 0) {
const subCategoryIndex = fixedCategories[
categoryIndex
].secondary_categories.findIndex(
(subCategory) => subCategory.name === object.secondary_category.name
);
if (subCategoryIndex >= 0) {
fixedCategories[categoryIndex].secondary_categories[
subCategoryIndex
].tasks.push({
id: object.id,
name: object.name
});
} else {
const subCategory = {
name: object.secondary_category.name,
id: object.secondary_category.id,
tasks: [{
id: object.id,
name: object.name
}]
};
fixedCategories[categoryIndex].secondary_categories.push(subCategory);
}
} else {
const category = {
name: object.primary_category.name,
id: object.primary_category.id,
secondary_categories: [{
name: object.secondary_category.name,
id: object.secondary_category.id,
tasks: [{
id: object.id,
name: object.name
}]
}]
};
fixedCategories.push(category);
}
return fixedCategories;
});
console.log(fixedCategories);