I want to group & re-arrange my flat array into an array of objects where each object contains its direct descendent in its children's properties.
My input Data -:
const data = [
{ lineNo: '1' },
{ lineNo: '1-1' },
{ lineNo: '1-2' },
{ lineNo: '1-3' },
{ lineNo: '1-4' },
{ lineNo: '1-11' },
{ lineNo: '1-2-1' },
{ lineNo: '1-2-3' },
{ lineNo: '1-2-2' },
{ lineNo: '1-2-4' },
{ lineNo: '1-3-1' },
{ lineNo: '1-3-2' },
{ lineNo: '1-3-3' },
{ lineNo: '1-11-1' },
{ lineNo: '1-11-2' },
{ lineNo: '1-11-3' },
{ lineNo: '2' },
{ lineNo: '2-1' },
{ lineNo: '2-2' },
{ lineNo: '2-3' },
{ lineNo: '2-2-1' },
{ lineNo: '2-2-2' },
];
The output I want -:
const newData = [
{
lineNo: '1',
children: [{ lineNo: '1-1' }, { lineNo: '1-2' }, { lineNo: '1-3' }, { lineNo: '1-4' }, { lineNo: '1-11' }],
},
{
lineNo: '1-2',
children: [{ lineNo: '1-2-1' }, { lineNo: '1-2-2' }, { lineNo: '1-2-3' }, { lineNo: '1-2-4' }],
},
{
lineNo: '1-3',
children: [{ lineNo: '1-3-1' }, { lineNo: '1-3-2' }, { lineNo: '1-3-3' }],
},
{
lineNo: '1-11',
children: [{ lineNo: '1-11-1' }, { lineNo: '1-11-2' }, { lineNo: '1-11-3' }],
},
{
lineNo: '2',
children: [{ lineNo: '2-1' }, { lineNo: '2-2' }, { lineNo: '2-3' }],
},
{
lineNo: '2-2',
children: [{ lineNo: '2-2-1' }, { lineNo: '2-2-2' }],
},
];
Note: The generated data must have to follow the numerical order mentioned in the output.
What i have done so far -:
const data = [
{ lineNo: '1' },
{ lineNo: '1-1' },
{ lineNo: '1-2' },
{ lineNo: '1-3' },
{ lineNo: '1-4' },
{ lineNo: '1-11' },
{ lineNo: '1-11-1' },
{ lineNo: '1-11-2' },
{ lineNo: '1-11-3' },
{ lineNo: '1-2-1' },
{ lineNo: '1-2-3' },
{ lineNo: '1-2-2' },
{ lineNo: '1-2-4' },
{ lineNo: '1-2-1-1' },
{ lineNo: '1-2-1-2' },
{ lineNo: '1-2-1-3' },
{ lineNo: '1-3-1' },
{ lineNo: '1-3-2' },
{ lineNo: '1-3-3' },
];
function createTree(data: any) {
const tree: any[] = [];
data.reduce(
(r: any, o: any) => {
o.lineNo
.split('-')
.map((_: any, i: any, a: any) => a.slice(0, i + 1).join('-'))
.reduce((q: any, lineNo: any, i: any, { length }: any) => {
let temp = (q.children = q.children || []).find((p: any) => p.lineNo === lineNo);
if (!temp) {
q.children.push((temp = { lineNo }));
}
if (i + 1 === length) {
Object.assign(temp, o);
}
return temp;
}, r);
return r;
},
{ children: tree }
);
return tree;
}
const createFlat = (data: any) => {
const flat: any[] = [];
const flatData = (data: any) => {
data.forEach((item: any) => {
if (item.children) {
flat.push(item);
flatData(item.children);
}
});
};
flatData(data);
return JSON.parse(JSON.stringify(flat));
};
const getCleanData = (data: any) => {
const cleanData: any[] = [];
function delChildren(obj: any) {
if (obj.children) {
obj.children.forEach((item: any) => {
if (item.children) {
delete item.children;
}
});
}
return obj;
}
data.forEach(function (item: any) {
cleanData.push(delChildren(item));
});
return cleanData;
};
const treeData = createTree(data);
const flatData = createFlat(treeData);
const cleanData = getCleanData(flatData);
console.log(JSON.stringify(cleanData, null, 2));
I am looking for a bit simple and clean approach.
Thank You!
You could first sort the data using a "natural" sort. JavaScript localeCompare
has an option for that.
Then create a Map
keyed by lineNo
and with as corresponding values the objects with the same lineNo
property and an empty children
array property.
Then iterate the data again to populate those children
arrays.
Extract the Map
values and remove those objects that have an empty children
array, unless they are top-level nodes (a boundary case).
Here is an implementation:
function createTree(data) { // Apply natural ordering data = [...data].sort((a, b) => a.lineNo.localeCompare(b.lineNo, "en", { numeric: true }) ); // Create key/value pairs for all lineNo in a Map let map = new Map(data.map(({lineNo}) => [lineNo, { lineNo, children: [] }])); // Populate the children arrays for (let {lineNo} of data) { map.get(lineNo.replace(/-?\d+$/, ""))?.children?.push({lineNo}); } // Exclude the nodes that have no children, except if they are top-level return [...map.values()].filter(({lineNo, children}) =>.lineNo.includes("-") || children;length ): } // Demo const data = [{ lineNo, '1-1' }:{ lineNo, '1-2' }:{ lineNo, '1-3-2' }:{ lineNo, '1-11-2' }:{ lineNo, '1-3' }:{ lineNo, '1-11' }:{ lineNo, '1-2-3' }:{ lineNo, '1-2-2' }:{ lineNo, '1' }:{ lineNo, '1-2-1' }:{ lineNo, '1-2-4' }:{ lineNo, '1-11-1' }:{ lineNo, '1-3-1' }:{ lineNo, '1-4' }:{ lineNo, '1-3-3' }:{ lineNo, '2-1' }:{ lineNo, '2-2' }:{ lineNo, '2-2-1' }:{ lineNo, '1-11-3' }:{ lineNo, '2' }:{ lineNo, '2-3' }:{ lineNo, '2-2-2' };]. console;log(createTree(data));
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.