tree-fns
tree-fns provides simple utility functions for tree structure.
Each transformation function is non-destructive, making it suitable for working with immutable tree structures.
Usage
tree-fns is available for Deno and Node.js.
Deno
import { TreeNode, walk } from 'https://deno.land/x/tree_fns@v0.1.0/mod.ts';
npm
npm i tree-fns
Development
Prerequisite
- deno >= 1.20
Model
const tree: TreeNode = {
id: 'root',
children: [
{
id: '1',
children: [],
},
{
id: '2',
children: [],
},
],
};
const tree: TreeNode<{ data: string }> = {
id: 'root',
data: 'yay',
children: [],
};
Functions
walk(tree, visit)
Only pre-order traversing is supported.
walk(
{
id: 'root',
children: [
{
id: '1',
children: [{ id: '1-1', children: [] }],
},
{
id: '2',
children: [{ id: '2-1', children: [] }],
},
],
},
(node, location) => {
console.log(node.id); // "root" -> "1" -> "1-1" -> "2" -> "2-1"
if (node.id === '1') {
console.log(location); // { parentPath: ["root"], index: 0 }
}
}
);
findNode(tree, test)
| findNodeById(tree, id)
const tree: TreeNode = {
id: 'root',
children: [
{
id: '1',
children: [{ id: '1-1', children: [] }],
},
{
id: '2',
children: [{ id: '2-1', children: [] }],
},
],
};
const node = findNode(tree, (node) => node.id === '1');
// [
// {
// id: '1',
// children: [{ id: '1-1', children: [] }],
// },
// {
// parentPath: ['root'],
// index: 0,
// },
// ]
findNode(tree, (node) => node.id === 'x'); // undefined
or
const node = findNodeById(tree, '1');
map(tree, mapNode)
const tree: TreeNode<{ data: string }> = {
id: '1',
data: 'foo',
children: [
{
id: '2',
data: 'bar',
children: [],
},
],
};
const mapped = map<{ data: string }>(tree, (node) => ({
...node,
data: `#${node.data}`,
}));
// {
// id: '1',
// data: '#foo',
// children: [
// {
// id: '2',
// data: '#bar',
// children: [],
// },
// ],
// }
copy(tree)
const tree = {
id: '1',
children: [{ id: '2', children: [] }],
};
const copied = copy(tree);
// {
// id: '1',
// children: [{ id: '2', children: [] }],
// }
console.log(tree === copied); // false
addNode(tree, nodeToBeAdded, dest)
const srcTree = {
id: '1',
children: [{ id: '2', children: [] }],
};
const nodeToBeAdded = { id: '3', children: [] };
const destTree = addNode(srcTree, nodeToBeAdded, { parentId: '1', index: 0 });
// {
// id: '1',
// children: [
// { id: '3', children: [] },
// { id: '2', children: [] },
// ],
// }
removeNode(tree, id)
const srcTree = {
id: '1',
children: [
{ id: '2', children: [] },
{ id: '3', children: [] },
],
};
const [destTree, removedNode] = removeNode(srcTree, '3');
console.log(removedNode); // { id: '3', children: [] }
console.log(destTree);
// {
// id: '1',
// children: [
// { id: '2', children: [] },
// ],
// }
removeNode(srcTree, 'x'); // undefined
moveNode(tree, id, dest)
const srcTree = {
id: '1',
children: [
{ id: '2', children: [] },
{ id: '3', children: [] },
],
};
const destTree = moveNode(srcTree, '2', { parentId: '3', index: 0 });
// {
// id: '1',
// children: [
// { id: '3', children: [
// { id: '2', children: [] }
// ] }
// ],
// }
flatten(tree)
const tree = {
id: '1',
children: [
{ id: '2', children: [] },
{ id: '3', children: [] },
],
};
const flattened = flatten(tree);
// [
// [
// {
// id: '1',
// children: [
// { id: '2', children: [] },
// { id: '3', children: [] },
// ],
// },
// { parentPath: [], index: 0 },
// ],
// [{ id: '2', children: [] }, { parentPath: ['1'], index: 0 }],
// [{ id: '3', children: [] }, { parentPath: ['1'], index: 1 }],
// ]