1.0.6 • Published 2 years ago

ts-tree-struct v1.0.6

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

TS TREE STRUCT

Just another tree data structure implementation in TS

Installation

npm install --save ts-tree-struct

Examples

Import required classes

import { Tree, TreeNode } from "ts-tree-struct";

Create tree

import { Tree, TreeNode } from "ts-tree-struct";
const tree = new Tree(
    //Tree requires a node to be used as root
    new TreeNode(
        "root", //key: string | number, required
        { foo: "bar" }, //data: any, optional, default as key
        [ new TreeNode("node#1", {foo: "bir"}) ], //children: TreeNode[], optional, default as []
    )
)

Tree props and methods

Get root node

> tree.root

> {
    key: 'root',
    data: { foo: 'bar' },
    parent: undefined,
        _children: [
        {
            key: 'node#1',
            data: { foo: 'bir' },
            parent: *this*,
            _children: []
        }
    ]
}

Get a node by key...

> tree.findOne("node#1")

> {
    key: 'node#1',
    data: { foo: 'bir' },
    parent: {
        key: 'root',
        data: { foo: 'bar' },
        parent: undefined,
        _children: [ *this* ]
    },
    _children: []
}

...or pass a find function

> tree.findOne((node) => node.key === "node#1")

> {
    key: 'node#1',
    data: { foo: 'bir' },
    parent: {
        key: 'root',
        data: { foo: 'bar' },
        parent: undefined,
        _children: [ *this* ]
    },
    _children: []
}

Find many nodes a time

> tree.findMany((node) => node.data.foo[0] === "b")

> [
    {
        key: 'root',
        data: { foo: 'bar' },
        parent: undefined,
        _children: [
            {
                key: 'node#1',
                data: { foo: 'bir' },
                parent: {
                    key: 'root',
                    data: { foo: 'bar' },
                    parent: undefined,
                    _children: [ *this* ]
                },
                _children: []
            }
        ]
    },
    {
        key: 'node#1',
        data: { foo: 'bir' },
        parent: {
            key: 'root',
            data: { foo: 'bar' },
            parent: undefined,
            _children: [ *this* ]
        },
        _children: []
    }
]

Insert a node

> tree.insertAt(
    "node#1", //key of target node
    new TreeNode("node#2", {foo: "bor"}) //node to insert
)

> {
    key: 'root',
    data: { foo: 'bar' },
    parent: undefined,
    _children: [
        {
            key: 'node#1',
            data: { foo: 'bir' },
            parent: *root*,
            _children: [
                {
                    key: 'node#2',
                    data: { foo: 'bor' },
                    parent: *node#1*,
                    _children: []
                }
            ]
        }
    ]
}

Remove a node

> tree.remove("node#2")

> {
    key: 'root',
    data: { foo: 'bar' },
    parent: undefined,
    _children: [
        {
            key: 'node#1',
            data: { foo: 'bir' },
            parent: *root*,
            _children: []
        }
    ]
}

Traversing

This is the signature of the traverse function

traverse(
    walker: {
        onEnter: (node: TreeNode, context?: Record<string, any>) => unknown
        onLeave?: (node: TreeNode, context?: Record<string, any>) => unknown
    },
    context: Record<string, any> = {},
    node: TreeNode = this.root
): Record<string, any>

walker: required, an object that must contains an 'onEnter' function and on optional 'onLeave' function. The node that is currently analysed is passed as first argument and the context object as second argument;

context: optional, default as {}, an object that is passed to every walker's call. Useful to pass initial variables or to hold temporary values;

node: optional, default tree.root, tree node that represent the entry point of traversing.

an example of tree traversing is the Tree.count function:

count(): number {
    const context = {count: 0}
    this.traverse(
        {
            onEnter: (node, context?) => {
                context!.count += node.childrenCount;
            },
            onLeave: (node, context?) => {
                if (!node.parent)
                    context!.count += 1;
            },
        },
        context
    )
    return context.count;
}

Iterate tree

> [...tree.preOrderTraversal()].map(x => x.key);

> [ "root", "node#1" ]

> [...tree.postOrderTraversal()].map(x => x.key);

> [ "node#1", "root" ] 

Count nodes

> tree.count()

> { count: 2 }

TreeNode props and methods

> tree.root.hasChildren

> true
> tree.root.childAt(0).isLeaf 

> true
> tree.root.childrenCount

> 2

Access child at index

> tree.root.childAt(0)

> {
    key: 'node#1',
    data: { foo: 'bir' },
    parent: {
        key: 'root', 
        data: { foo: 'bar' },
        parent: undefined,
        _children: [ *this* ],
        _childCount: 1
    },
    _children: [],
    _childCount: 0
}

Access parent

> tree.findOne("node#1").parent

> {
    key: 'root',
    data: { foo: 'bar' },
    parent: undefined,
    _children: [
        {
            key: 'node#1',
            data: { foo: 'bir' },
            parent: *root*,
            _children: []
        }
    ]
}

Insert child

tree.root.insertChild(new TreeNode("node#2", { foo: "bor" }))

OR

tree.root.insertChildAt(0, new TreeNode("node#3", { foo: "bur" }))

Remove child

tree.root.removeChild("node#2")

OR

tree.root.removeChildAt(0)
1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago