Last active
January 27, 2023 01:36
-
-
Save angeloevangelista/1fb9c132ef9ff198093545a0549a71b6 to your computer and use it in GitHub Desktop.
Recursive strategy to extract paths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface TreeType { | |
name: string; | |
children: TreeType[]; | |
} | |
const originalTree: TreeType = { | |
name: "root", | |
children: [ | |
{ children: [], name: "products" }, | |
{ | |
name: "Cars", | |
children: [ | |
{ | |
name: "Chevrolet", | |
children: [ | |
{ name: "Agile", children: [] }, | |
{ name: "Onix", children: [] }, | |
{ name: "Tracker", children: [] }, | |
], | |
}, | |
{ | |
name: "Fiat", | |
children: [ | |
{ name: "Cronus", children: [] }, | |
{ name: "Mobi", children: [] }, | |
{ name: "Palio", children: [] }, | |
], | |
}, | |
{ | |
name: "Volkswagen", | |
children: [ | |
{ name: "Gol", children: [] }, | |
{ name: "Fox", children: [] }, | |
{ name: "SpaceFox", children: [] }, | |
], | |
}, | |
{ | |
name: "Renault", | |
children: [ | |
{ name: "Sandero", children: [] }, | |
{ name: "Logan", children: [] }, | |
{ name: "Clio", children: [] }, | |
], | |
}, | |
], | |
}, | |
], | |
}; | |
/** | |
* Disclaimer: When I wrote this function, only God and I knew how it worked. | |
* Now, only God nows. Good luck if You intend to understand it. | |
* | |
* @param node The current node You wanna extract the children | |
* @param parentPath The node parent path | |
* @returns A list of found children | |
*/ | |
function extractPaths(node: TreeType, parentPath: string): string[] { | |
const paths: string[] = []; | |
if (node.children.length !== 0) { | |
node.children.forEach((nodeChild) => { | |
const childPrefix = `${parentPath}/${nodeChild.name}`; | |
const innerPaths = extractPaths(nodeChild, childPrefix); | |
paths.push(...innerPaths); | |
}); | |
} | |
paths.push(...node.children.map((p) => `${parentPath}/${p.name}`)); | |
return paths.sort((a, b) => a.length - b.length); | |
} | |
/** | |
* Disclaimer: God, again, gave me that divine help to complete this. | |
* Now it's on You. Good luck! | |
* | |
* @param paths The paths You wanna get the tree from | |
* @returns The full tree from provided paths | |
*/ | |
function recoverTreeFromPaths(paths: string[]): TreeType { | |
const getTreeFromPath = (path: string, tree: TreeType): TreeType => { | |
const pathSegments = path.split("/").filter((p) => p.trim()); | |
const [firstPathSegment, ...restOfPathSegments] = pathSegments; | |
const existentChildIndex = tree.children.findIndex( | |
(p) => p.name === restOfPathSegments[0] | |
); | |
if (restOfPathSegments.length !== 0) { | |
if (existentChildIndex !== -1) { | |
tree.children[existentChildIndex] = getTreeFromPath( | |
restOfPathSegments.join("/"), | |
{ | |
name: firstPathSegment, | |
children: tree.children[existentChildIndex].children, | |
} | |
); | |
} else { | |
tree.children.push( | |
getTreeFromPath(restOfPathSegments.join("/"), { | |
name: firstPathSegment, | |
children: [], | |
}) | |
); | |
} | |
} | |
return { | |
name: firstPathSegment, | |
children: tree.children, | |
}; | |
}; | |
const reducedTree = paths.reduce<TreeType>( | |
(acc, next) => getTreeFromPath(next, acc), | |
{ | |
name: "", | |
children: [], | |
} | |
); | |
return reducedTree; | |
} | |
const extractedPaths = extractPaths(originalTree, originalTree.name); | |
const recoveredTree = recoverTreeFromPaths(extractedPaths); | |
console.dir( | |
{ | |
originalTree, | |
extractedPaths, | |
recoveredTree, | |
}, | |
{ depth: null } | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment