Struggling with the logic: Trying my best to explain it. I have an array of objects like:
[
{ categoryPath: "client/client one/client two" description: "test description"},
{ categoryPath: "client/client one" description: "test description"},
{ categoryPath: "research/research one" description: "test description"}
]
EDIT: the expected output, I did a mistake in the expected output. The client One category should have two attributes, as in the input Object, we can see that it second object has categoryPath as, client/client one- so the description of this should come under the client one hierarchy.
my need is to convert it into an array of objects like the below:
[{
categoryName: 'client',
categoryId: '0',
subcategories: [
{
categoryId: '1',
categoryName: 'client one',
subcategories: [{
categoryId: '2',
categoryName: 'client two',
attributes: [
{
description: 'test description '
}],
}],
attributes: [{
description: 'test description '
},
{
description: 'test description '
} ]
},
],
attributes: []
},
{
categoryName: 'research',
categoryId: '0',
subcategories: [
{
categoryId: '1',
categoryName: 'research one',
attributes: [
{
description: 'test description '
}],
}],
},
],
attributes: []
},
The code which I have written is keep getting complex, not sure if you'll get it, but here: But if you check my code it is returning the circular array issue, and nesting the parent categories in the object.
let baseObj = {
name : '',
parentName:'',
subCat: [],
att: [],
level: 0,
}
let masterObj = {};
let baseId = {};
for (let i = 0; i < arr.length; i ) {
//console.log(arr[i]);
let splitCat = arr[i].cat.split('/');
let addAttData = [...splitCat, {att:arr[i].name}];
if (!masterObj[splitCat[0]]) {
masterObj[splitCat[0]] = {...baseObj};
masterObj[splitCat[0]].name = splitCat[0];
}
getParentRec(splitCat[0], addAttData, masterObj);
}
console.log(JSON.stringify(masterObj,null,2));
Object.keys(masterObj).forEach((item, index) => {
//client//research level
console.log('new', item, masterObj[item]);
for(let i = masterObj[item].level ; i> 0; i--) {
console.log(i, 'item', masterObj[item].level);
let obj = getObj(masterObj[item]);
console.log('obj', obj);
console.log('whole fir',masterObj[item]);
obj.forEach((objItem) => {
let prName = masterObj[item][objItem].parentName;
console.log('current', masterObj[item][objItem]);
if (prName !== item) {
let newObj = {...masterObj[item][objItem]};
masterObj[item][prName].subCat.push(newObj);
console.log('v',prName, masterObj[item][prName]); delete masterObj[item][objItem];
console.log('after delete', masterObj[item][objItem]);
console.log('whole',masterObj[item]);
} else {
console.log('masterItem', masterObj[item]);
masterObj[item].subCat.push(masterObj[item][objItem]);
console.log(item, 'final',JSON.stringify(masterObj[item], null, 2));
}
})
masterObj[item].level = masterObj[item].level - 1;
}
})
//console.log(JSON.stringify(masterObj, null, 2));
function getObj (obj) {
console.log(Object.keys(obj), obj.level);
let objFound= Object.keys(obj).filter(filterItem => obj[filterItem].level === obj.level);
console.log('found', obj[objFound]);
return objFound;
}
function getParentRec(parentId, arrObj, masterObj) {
//console.log('start', masterObj);
for (let i = 1; i< arrObj.length - 1 ;i ) {
let obj = {...baseObj};
//console.log('obj', obj);
let lastObj = '';
lastObj = arrObj[i];
obj.name = lastObj;
if ( i 1 === arrObj.length - 1) {
obj.att = [arrObj[arrObj.length - 1]];
}
obj.parentName = arrObj[i -1];
obj.level = i;
/* console.log('l', lastObj, i);
console.log('iobj', obj);
console.log('as ',masterObj[parentId][lastObj]); */
if (!masterObj[parentId][lastObj]) {
//console.log('wo', i);
masterObj[parentId][lastObj] = obj;
if (i >= masterObj[parentId].level) {
masterObj[parentId].level = i;
}
//console.log('masterObj', masterObj);
}
}
return masterObj;
}
Please help with the logic, it is for creating a folder expand like UI in react. So anything which is having a similar parent category will appear in that hierarchy. Else it will form a new hierarchy like research. But in the case of the client is getting inside the parent category client and creating hierarchy like at the sibling level.
CodePudding user response:
Try this one with Array.reduce
const data = [{ categoryPath: "client/client one/client two", description: "test description"},{ categoryPath: "client/client one", description: "test description"},{ categoryPath: "research/research one", description: "test description"}];
const transforming = data.reduce((acc, {categoryPath, description}) => {
const leaf = categoryPath.split('/').reduce((parent, categoryName, index) => {
acc[categoryName] = acc[categoryName] || {
categoryId: index.toString(),
categoryName: categoryName,
subcategories: [],
attributes: []
};
if (!acc[parent].subcategories.find(child => child.categoryName === categoryName)) {
acc[parent].subcategories.push(acc[categoryName]);
}
return categoryName;
}, '-');
acc[leaf].attributes.push({description});
return acc;
}, { '-': { subcategories: [] } });
const result = transforming['-'].subcategories;
console.log(JSON.stringify(result));
Edit
const data = [{ categoryPath: "client/client one/client two", description: "test description"},{ categoryPath: "client/client one", description: "test description"},{ categoryPath: "research/research one", description: "test description"}];
const transforming = data.reduce((acc, {categoryPath, description}) => {
categoryPath.split('/').reduce((parent, categoryName, index) => {
acc[categoryName] = acc[categoryName] || {
categoryId: index.toString(),
categoryName: categoryName,
subcategories: [],
attributes: []
};
if (index > 0) {
acc[categoryName].attributes.push({description})
}
if (!acc[parent].subcategories.find(child => child.categoryName === categoryName)) {
acc[parent].subcategories.push(acc[categoryName]);
}
return categoryName;
}, '-');
return acc;
}, { '-': { subcategories: [] } });
const result = transforming['-'].subcategories;
console.log(JSON.stringify(result));