I have array with data:
const data = [
{ id: 1, type: 'type 1'},
{ id: 2, type: 'type 2', subtype: 'subtype 2'},
{ id: 3, type: 'type 2', subtype: 'subtype 3'},
{ id: 4, type: 'type 2', subtype: 'subtype 4'},
{ id: 5, type: 'type 3', subtype: 'subtype 3'},
]
And I need to build the tree like this:
type 1
type 2
subtype 2
subtype 3
subtype 4
type 3
subtype 3
CodePudding user response:
In case the OP's example data
items keep their simple type
/subtype
structure the approach boils down to a grouping task where the type
's value is the key (property name) of a new group of subtype
entries (continuing the object structure) or items (changing to an array structure).
Aggregating (grouped) data at an object is a classic reduce
task.
Used language features:
const data = [
{ id: 1, type: 'type 1' },
{ id: 2, type: 'type 2', subtype: 'subtype 2' },
{ id: 3, type: 'type 2', subtype: 'subtype 3' },
{ id: 4, type: 'type 2', subtype: 'subtype 4' },
{ id: 5, type: 'type 3', subtype: 'subtype 3' },
];
console.log(
data
.reduce((result, { type, subtype = null }) => {
const typeGroup = (result[type] ??= {});
if (subtype !== null) {
typeGroup[subtype] = {};
}
return result;
}, {})
)
console.log(
data
.reduce((result, { type, subtype = null }) => {
const groupedSubtypeList = (result[type] ??= []);
if (subtype !== null) {
groupedSubtypeList.push(subtype);
}
return result;
}, {})
)
console.log(
Object
.entries(
// same reduce functionality as one example before.
data
.reduce((result, { type, subtype = null }) => {
const groupedSubtypeList = (result[type] ??= []);
if (subtype !== null) {
groupedSubtypeList.push(subtype);
}
return result;
}, {})
)
// additional mapping over the reduce result's entries.
.map(([type, subtypes]) => {
const typeItem = {
type: type.replace('type', '').trim(),
};
if (subtypes.length >= 1) {
typeItem.subtypes = subtypes
.map(subtype => ({
subtype: subtype.replace('subtype', '').trim(),
}));
}
return typeItem;
})
)
.as-console-wrapper { min-height: 100%!important; top: 0; }
CodePudding user response:
Edit 2 - edited for more structured way
const data = [{
id: 1,
type: 'type 1'
},
{
id: 2,
type: 'type 2',
subtype: 'subtype 2'
},
{
id: 3,
type: 'type 2',
subtype: 'subtype 3'
},
{
id: 4,
type: 'type 2',
subtype: 'subtype 4'
},
{
id: 5,
type: 'type 3',
subtype: 'subtype 3'
},
];
var pretype = "";
//const newArr = data.map(change);
var pretype = "";
var preindex = -1;
const arr2 = []
data.forEach(function(idx) {
if (pretype != idx.type) {
//console.log(idx.type);
arr2.push({
//'id': idx.id,
"type": idx.type.replace("type ", "")
});
preindex ;
}
if (idx.subtype) {
//console.log("pr", preindex, arr2[preindex], arr2[preindex]["subtypes"])
if (arr2[preindex]["subtypes"] == undefined)
arr2[preindex]["subtypes"] = [];
arr2[preindex]["subtypes"].push({
"subtype": idx.subtype.replace("subtype ", "")
})
}
pretype = idx.type;
});
console.log("arr2: ",arr2)
console.log("flat: ",JSON.stringify(arr2));
function change(id) {
if (pretype != id.type)
console.log(id.type);
if (id.subtype)
console.log(id.subtype)
pretype = id.type;
}
CodePudding user response:
Build any object from array. Merge the values when you have same keys
const data = [
{ id: 1, type: "type 1" },
{ id: 2, type: "type 2", subtype: "subtype 2" },
{ id: 3, type: "type 2", subtype: "subtype 3" },
{ id: 4, type: "type 2", subtype: "subtype 4" },
{ id: 5, type: "type 3", subtype: "subtype 3" },
];
const buildTreeObj = (arr) => {
const obj = {};
arr.forEach((item) => {
if (obj[item.type]) {
obj[item.type].subs.push(item.subtype);
} else {
obj[item.type] = {
type: item.type,
subs: item.subtype ? [item.subtype] : [],
};
}
});
return Object.values(obj);
};
console.log(buildTreeObj(data));