Skip to content

Instantly share code, notes, and snippets.

@angeloevangelista
Last active January 27, 2023 01:36
Show Gist options
  • Save angeloevangelista/1fb9c132ef9ff198093545a0549a71b6 to your computer and use it in GitHub Desktop.
Save angeloevangelista/1fb9c132ef9ff198093545a0549a71b6 to your computer and use it in GitHub Desktop.
Recursive strategy to extract paths
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