I have an array that looks like this:
const arr = [
{
parent: 'A',
children: ['B'],
},
{
parent: 'B',
children: ['C'],
},
{
parent: 'C',
children: ['D']
}];
and I want to create a function that will take this array and result in the following object:
const result = {
parent: 'A',
children: [{
parent: 'B',
children: [{
parent: 'C',
children: [{
parent: 'D',
children: []
}]
}]
}]
};
so the result type would look like:
type Result = {
parent: string;
children: Result[];
};
What I've tried so far:
type TInput = {
parent: string;
children: string[];
};
type Result = {
parent: string;
children: Result[];
};
// can assume we know initial parent is 'A'
const fn = (parent: string, inputArr: TInput[]) => {
const result: TResult[] = [];
let newParent: string[] = [];
while (newParent.length !== 0) {
const index = inputArr.findIndex(
(input) => input.parent === parent
);
result.push({
parent: inputArr[index].parent,
children: [], // need to populate on next pass?
});
newParent = inputArr[index].children;
}
return result;
};
I don't know how many objects will be in the input array, but can assume first object is known to be initial parent/child ('A' in the example). Any help much appreciated. Thanks
CodePudding user response:
If I get you right, one way you can go is recursive function. Read inline comments:
// Array
const arr = [
{
parent: 'A',
children: ['B'],
},
{
parent: 'B',
children: ['C'],
},
{
parent: 'C',
children: ['D']
}
];
// Alphabet
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.toUpperCase().split('');
// Recursive function
const rf = (arr, i = 0) => {
// Result object
let result = [];
// Loop through array of objects
for(const obj of arr) {
// If parent or children equals current letter
if(obj.parent === alphabet[i] || obj.children[0] === alphabet[i]) {
// Form object in array
result = [{
parent: alphabet[i],
children: rf(arr, i 1) // Go recursive with letter 1
}];
}
}
// Return result
return result;
}
// Test
console.log(rf(arr)[0]);
CodePudding user response:
This seems to do the job :
This is the ts
version :
// here i just copy your data
const data = [{
parent: 'A',
children: ['B'],
},
{
parent: 'C',
children: ['D']
},
{
parent: 'B',
children: ['C'],
}
];
const expectedResult = {
parent: 'A',
children: [{
parent: 'B',
children: [{
parent: 'C',
children: [{
parent: 'D',
children: []
}]
}]
}]
};
type TInput = {
parent: string;
children: string[];
};
type TResult = {
parent: string;
children: TResult[];
};
// there is the function that takes an input (the parent element) and an array (all the children)
const parseArray = (obj: TInput, arr: TInput[]): TResult => {
return {
parent: obj.parent,
// if the children exists on the array, we use it, else we create an empty one, which will be used to recusivly generate the tree
children: obj.children.map(child => data.find(e => e.parent === child) ?? {
parent: child,
children: []
}).map(e => parseArray(e, arr))
}
}
// we get the root obj (as you said the first el)
const root = data.shift()!
// and we call the function
console.log(parseArray(root, data))
// we verify that the objects are the same using json (directly using == on objects compares their locations on the disk)
console.log(JSON.stringify(parseArray(root, data)) === JSON.stringify(expectedResult))
And this is the snipped (we can't run ts directly on snippets) :
// here i just copy your data
const data = [{
parent: 'A',
children: ['B'],
},
{
parent: 'C',
children: ['D']
},
{
parent: 'B',
children: ['C'],
}
];
const expectedResult = {
parent: 'A',
children: [{
parent: 'B',
children: [{
parent: 'C',
children: [{
parent: 'D',
children: []
}]
}]
}]
};
// there is the function that takes an input (the parent element) and an array (all the children)
const parseArray = (obj, arr) => {
return {
parent: obj.parent,
// if the children exists on the array, we use it, else we create an empty one, which will be used to recusivly generate the tree
children: obj.children.map(child => data.find(e => e.parent === child) ?? {
parent: child,
children: []
}).map(e => parseArray(e, arr))
}
}
// we get the root obj (as you said the first el)
const root = data.shift()
// and we call the function
console.log(parseArray(root, data))
// we verify that the objects are the same using json (directly using == on objects compares their locations on the disk)
console.log(JSON.stringify(parseArray(root, data)) === JSON.stringify(expectedResult))