Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/marianmeres/tree
Base tree class providing common traversal, lookup and node manipulation operations.
https://github.com/marianmeres/tree
tree tree-structure
Last synced: 20 days ago
JSON representation
Base tree class providing common traversal, lookup and node manipulation operations.
- Host: GitHub
- URL: https://github.com/marianmeres/tree
- Owner: marianmeres
- License: mit
- Created: 2024-02-24T14:12:49.000Z (11 months ago)
- Default Branch: master
- Last Pushed: 2024-09-27T07:52:31.000Z (3 months ago)
- Last Synced: 2024-12-12T23:48:22.246Z (26 days ago)
- Topics: tree, tree-structure
- Language: TypeScript
- Homepage:
- Size: 428 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @marianmeres/tree
Base [tree]() class providing
common traversal, lookup and node manipulation operations.## Install
```shell
$ npm i @marianmeres/tree
```## Example usage
```typescript
import { Tree, TreeNode } from '@marianmeres/tree';const tree = new Tree();
// no root node was provided yet, so the tree is zero in size
assert(!tree.root);
assert(tree.size() === 0);// add some nodes
// "A" below will become "root" as it is the first child (the tree must have exactly 1 root)
const A = tree.appendChild('A');
tree.appendChild(new TreeNode('A')); // alternative to above
assert(tree.root === A);const AA = tree.appendChild('AA');
const AB = tree.appendChild('AB');// now append to nodes directy
const AAA = AA.appendChild('AAA');
const AAB = AA.appendChild('AAB');
const ABA = AB.appendChild('ABA');
const ABB = AB.appendChild('ABB');// there is also `tree.insert` method, which works similar (we can specify the parent node)
const AAAA = tree.insert(AAA.key, 'AAAA');
const AAAB = tree.insert(AAA.key, 'AAAB');
// const AAAA = AAA.appendChild('AAAA'); // same effect as above
// const AAAB = AAA.appendChild('AAAB');// check visually (the `toString` provides simple human readable plain text representation)
assert(tree.toString() === `
A
AA
AAA
AAAA
AAAB
AAB
AB
ABA
ABB
`.trim());// we have 9 nodes in total
assert(tree.size() === 9);// sub-brach AA has 5 (`size` accepts "fromNode" param)
assert(tree.size(AA) === 5);// Each node has a unique string "key" (which is auto-created). Most lookup methods are
// based on this key. Node also has a "value" which is any raw value and which can be
// used in lookups as well. In this example, the values are plain strings.// lookups
assert(tree.find(A.key) === A);
assert(tree.findBy('AB') === AB);
tree.findBy(propertyValue, propertyName) // if the values were objects// contains lookup
assert(tree.contains(AB.key));
assert(!AB.contains(AAB.key));// the tree is fully serializable (internally via JSON.stringify/parse)
const dump = tree.dump();
assert(typeof dump === 'string');
const restored = new Tree().restore(dump);
// const restored = Tree.factory(dump); // same as above
assert(tree.toString() === restored.toString());// traversal...
for (let node of tree.preOrderTraversal()) {
// each node exposes these props
node.children // array of direct child nodes
node.depth // number
node.isLeaf // boolean
node.isRoot // boolean
node.key // auto-generated unique key
node.parent // reference to parent node
node.path // hierarchy path to node as array of nodes from root (top-down)
node.root // refererence to root node
node.siblings // array of siblings
node.tree // reference to the tree the node belongs to
node.value // actual stored value (string in our example)// and methods
node.deepClone()
node.toJSON()
node.appendChild(valueOrNode: T | TreeNode)
node.removeChild(key: string)
node.replaceChild(key: string, valueOrNode: T | TreeNode)
node.resetChildren(valuesOrNodes: (T | TreeNode)[] = [])
node.previousSibling()
node.nextSibling()
node.moveSiblingIndex(toIndex: number)
node.contains(key: string)
node.toString()
}// lowest common ancestor lookup
assert(tree.findLCA(AAB.key, AAAB.key) === AA);// node/subtree removal
tree.remove('nodeKey');
node.removeChild(key: string)
node.replaceChild(key: string, valueOrNode: T | TreeNode)
node.resetChildren(values: (T | TreeNode)[] = [])// node/subtree move and copy
tree.move(sourceNodeKey: string, targetNodeKey: string);
tree.copy(sourceNodeKey: string, targetNodeKey: string);// node siblings
assert(AAAA.nextSibling() === AAAB);
assert(AAAB.previousSibling() === AAAA);// siblings reorder
assert(AAAB.siblingIndex === 1);
assert(AAAB.moveSiblingIndex(0).siblingIndex === 0);// tree can be marked as readonly where ALL modifying operations fail, e.g.
const t = Tree.factory(dump, true);
assert(t.readonly);
assert.throws(() => t.appendChild('foo'));
// ...
```