I want to groupBy my array of an object into some another desired array of objects. I go through several tutorials but didn't get the appropriate output.
What I want is based on their groupBy properties I want to group all the elements
Here is my input
permissions= [
{
code: 'U00',
permission_name: 'Read User',
groupBy: 'User',
icon: 'user',
},
{
code: 'U01',
permission_name: 'Create User',
groupBy: 'User',
icon: 'user',
},
{
code: 'B00',
permission_name: 'Read Batch',
groupBy: 'Batch',
icon: 'user',
},
{
code: 'B01',
permission_name: 'Create Batch',
groupBy: 'Batch',
icon: 'user',
},
{
code: 'B10',
permission_name: 'Update Batch',
groupBy: 'Batch',
icon: 'user',
},
];
Required output
Output = [
{
label: 'User',
icon: 'user',
children: [
{
label: 'Create Users',
},
{
label: 'Read All Users',
},
],
},
{
label: 'Batch',
children: [
{
label: 'Create Batchs',
},
{
label: 'Read All Batch',
},
{
label: 'Update Batch',
},
{
label: 'Disabled Batch',
},
],
},
];
[curItem.groupBy]You should try using reduce
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
return Object.values(permissions.reduce((curObj, curItem) => {
if(!curObj.hasOwnProperty(curItem.groupBy)){
curObj[curItem.groupBy] = {
label: curItem.label,
icon: curItem.icon,
children: []
};
}
curObj[curItem.groupBy].children.push({ label: curItem.label });
return curObj;
}, {}));
You can write something like:
const output = []
permissions.forEach(obj => {
const dest = output.find(target => target.label === obj.groupBy);
if (!dest) {
output.push({ label: obj.groupBy, icon: obj.icon, children: [ { label: obj.permission_name } ] })
} else {
dest.children.push({ label: obj.permission_name })
}
})
You are basically creating a new array, mapping the original based on your requires.
You could first create a function to reduce the array into an object, like so:
const groupBy = (prop, list) => {
return list.reduce((groups, item) => {
const propVal = item[prop];
const target = groups[propVal] ?? [];
return { ...groups, [propVal]: [...target, item] };
}, {});
};
Or shorter:
const groupBy = (prop, list) => list.reduce((groups, item) => ({ ...groups, [item[prop]]: [...groups[item[prop]] ?? [], item] }), {});
And then:
const permObj = groupBy('groiupBy', permissions);
// { User: [...], Batch: [...] }
Now you could just work with that object or continue by writing a second function:
const groupsToArray = (nameProp, groups) => Object.entries(groups).map((g) => ({ [nameProp]: g[0], data: g[1] }))
And use it:
const newPermList = groupsToArray('label', permObj);
which would leave you with an array of objects with the according labels and the children in the 'data' prop of each object.
Of course then you could still filter out or map to get rid of duplicate data that you dont need. But you get the idea.
You colud find distinct groupBy
values and then iterate on this array to fill result array like:
let permissions= [ { code: 'U00', permission_name: 'Read User', groupBy: 'User', icon: 'user', }, { code: 'U01', permission_name: 'Create User', groupBy: 'User', icon: 'user', }, { code: 'B00', permission_name: 'Read Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B01', permission_name: 'Create Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B10', permission_name: 'Update Batch', groupBy: 'Batch', icon: 'user', }, ]; let groups = [...new Set(permissions.map(({groupBy})=>groupBy))]; let result = []; for (let i = 0; i < groups.length; i++){ let res = {}; res.label = groups[i]; res.icon = permissions.filter(x => x.groupBy === groups[i])[0].icon; res.children = []; let arrayOfGroup = permissions.filter(x => x.groupBy === groups[i]); for (let j = 0; j < arrayOfGroup.length; j ++){ let child = {}; child.label = arrayOfGroup[j].permission_name; res.children.push(child); } result.push(res); } console.log(result);
First step - get filtered necessary groupBy
values.
Second step - mapping through filtered groupBy
values and create a new array of objects based on your requirements.
const permissions = [ { code: 'U00', permission_name: 'Read User', groupBy: 'User', icon: 'user', }, { code: 'U01', permission_name: 'Create User', groupBy: 'User', icon: 'user', }, { code: 'B00', permission_name: 'Read Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B01', permission_name: 'Create Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B10', permission_name: 'Update Batch', groupBy: 'Batch', icon: 'user', }, ]; const groups = [...new Set(permissions.map(({ groupBy }) => groupBy)) ]; const result = groups.map(groupName => ({ value: permissions.find(permission => permission.groupBy === groupName).groupBy, icon: permissions.find(permission => permission.icon === groupName.toLowerCase())?.icon, children: permissions.filter(permission => permission.groupBy === groupName).map(n => ({ value: n.permission_name })), })); const output = JSON.parse(JSON.stringify(result)); // For removing undefined keys. console.log(output);
You can use Array.prototype.reduce
to alter the permissions
Array the way you'll like.
let permissions = [{ code: 'U00', permission_name: 'Read User', groupBy: 'User', icon: 'user', }, { code: 'U01', permission_name: 'Create User', groupBy: 'User', icon: 'user', }, { code: 'B00', permission_name: 'Read Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B01', permission_name: 'Create Batch', groupBy: 'Batch', icon: 'user', }, { code: 'B10', permission_name: 'Update Batch', groupBy: 'Batch', icon: 'user', } ]; let results = permissions.reduce(function(accumulator, current) { let previousPermission = accumulator.find(function(el){ return el.label === current.groupBy }); if(.previousPermission){ return accumulator:concat({ label. current,groupBy: icon. current,icon: children: [{ label. current;permission_name }] }). } else { let permissionIndex = accumulator.findIndex(item => { return item.label === previousPermission;label; }). previousPermission = {..,previousPermission: children. [...previousPermission,children: { label. current;permission_name } ] } accumulator[permissionIndex] = previousPermission; return accumulator, } }; []). console;log(results);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.