NaryTree v0.1.1 NaryTree View Source

NaryTree implements a data structure for an n-ary tree in which each node has zero or more children. A node in a tree can have arbitrary number of children and depth. Trees are unbalanced and children unordered.

Link to this section Summary

Functions

Add a child node to a tree root node. Returns an updated tree with added child

Add a child node to the specified tree node. Returns an updated tree with added child

Returns the children nodes of a tree

Delete a node in a tree. If the deleted node has children, the children will be moved up in hierarchy to become the children of the deleted node’s parent

Detach a branch in a tree. Returns the detached branch conplete with all its descendents as a new tree struct

Enumerates tree nodes, and applies function to each leaf nodes’ content. Similar to update_content/2, but applies only to leaf nodes

Invoked in order to access the value stored under key in the given term term

Converts a map into a tree

Get the node with the specified id from the tree

Invoked in order to access a node in a tree and update it at the same time

Check whether a node has non-empty content

Check whether a node is a leaf node

Check whether the argument is of NaryTree type

Check whether a node is a root node

Converts a list of nodes back into nodes map %{node1id => %NaryTree.Node{}, node2id => ...}

Merges a tree into another tree at the specified node point. Returns the resulting combined tree or :error if the specified node point doesn’t exist

Move children nodes from one node to another node

Create a new, empty tree

Create a new tree with a root node

Returns the parent node of a tree, or :empty if there is none

Invoked to “pop” the specified node from the tree

Prints a tree in hierarchical fashion. The second parameter is an optional function that accepts a node as a parameter. print_tree will output the return value of the function for each node in the tree

Put a node into the tree at the specified id. Put will replace the name and content attributes of the node at id with the attributes of the new nodes. The children and parent of the old node will remain the same so that the hierarchy structure remains the same

Returns the root node of a tree

Returns the sibling nodes of a node

Collects nodes of a tree by using depth-first traversal. Returns a list of NaryTree.Node structs

Converts a tree into a hierarchical map with children nodes embedded in an array

Enumerates tree nodes, and applies function to each node’s content. Returns updated tree, with new content for every nodes

Link to this section Types

Link to this type t() View Source
t() :: %NaryTree{
  nodes: [%NaryTree{nodes: term(), root: term()}],
  root: String.t()
}

Link to this section Functions

Add a child node to a tree root node. Returns an updated tree with added child.

    RootNode
    \
    ChildNode

Example

iex> tree = NaryTree.new(NaryTree.Node.new "Root node") |>
...>   NaryTree.add_child(NaryTree.Node.new("Child"))
iex> %NaryTree{root: key, nodes: nodes} = tree
iex> [child_id | _] = nodes[key].children
iex> nodes[child_id].name
"Child"
Link to this function add_child(tree, child, parent_id) View Source

Add a child node to the specified tree node. Returns an updated tree with added child.

  RootNode
    \
    BranchNode
        \
        New node

Example

iex> branch = NaryTree.Node.new("Branch Node")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...>   NaryTree.add_child(branch) |>
...>   NaryTree.add_child(NaryTree.Node.new("New node"), branch.id)
iex> Enum.count tree.nodes
3

Returns the children nodes of a tree.

Link to this function delete(tree, id) View Source
delete(NaryTree.t(), any()) :: :error

Delete a node in a tree. If the deleted node has children, the children will be moved up in hierarchy to become the children of the deleted node’s parent.

Deleting root node results in :error

Example

iex> branch = NaryTree.Node.new("Branch Node")
iex> leaf = NaryTree.Node.new("Leaf")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...>   NaryTree.add_child(branch) |>
...>   NaryTree.add_child(leaf, branch.id) |>
...>   NaryTree.delete(branch.id)
iex> tree.nodes[branch.id]
nil
iex> tree.nodes[tree.root].children   # leaf becomes root's child
[leaf.id]

Detach a branch in a tree. Returns the detached branch conplete with all its descendents as a new tree struct.

Example

iex> branch = NaryTree.Node.new("Branch Node")
iex> leaf = NaryTree.Node.new("Leaf")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...>   NaryTree.add_child(branch) |>
...>   NaryTree.add_child(leaf, branch.id)
iex> detached = NaryTree.detach(tree, branch.id)
iex> Enum.count detached.nodes
2
iex> detached.root
branch.id
Link to this function each_leaf(tree, func) View Source
each_leaf(NaryTree.t(), function()) :: NaryTree.t()

Enumerates tree nodes, and applies function to each leaf nodes’ content. Similar to update_content/2, but applies only to leaf nodes.

Link to this function fetch(nary_tree, id) View Source
fetch(NaryTree.t(), String.t()) :: {:ok, NaryTree.Node.t()} | :error

Invoked in order to access the value stored under key in the given term term.

This function should return {:ok, value} where value is the value under key if the key exists in the term, or :error if the key does not exist in the term.

Many of the functions defined in the Access module internally call this function. This function is also used when the square-brackets access syntax (structure[key]) is used: the fetch/2 callback implemented by the module that defines the structure struct is invoked and if it returns {:ok, value} then value is returned, or if it returns :error then nil is returned.

See the Map.fetch/2 and Keyword.fetch/2 implementations for examples of how to implement this callback.

Callback implementation for Access.fetch/2.

Converts a map into a tree

Example:

iex> tree = NaryTree.from_map %{name: “Root”, children: [%{name: “Left”}, %{name: “Right”}]} iex> Enum.count tree 3

Get the node with the specified id from the tree.

Example

iex> node = NaryTree.Node.new("Node")
iex> n = NaryTree.new(node) |>
...>     NaryTree.get(node.id)
iex> n.name
"Node"
Link to this function get_and_update(tree, id, fun) View Source

Invoked in order to access a node in a tree and update it at the same time

Example

iex> tree = NaryTree.new NaryTree.Node.new "Root"
iex> {old_node, new_tree} = NaryTree.get_and_update tree, tree.root, &({&1, %NaryTree.Node{&1 | content: :not_empty}})
iex> old_node.content
:empty
iex> NaryTree.root(new_tree).content
:not_empty
Link to this function has_content?(node) View Source
has_content?(NaryTree.Node.t()) :: boolean()

Check whether a node has non-empty content.

Example

iex> node = NaryTree.Node.new "Node", content: %{c: "Content"}
iex> NaryTree.has_content? node
true

Check whether a node is a leaf node.

Example

iex> tree = NaryTree.new(NaryTree.Node.new("Root node")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf node"))
iex> [node_id] = tree.nodes[tree.root].children
iex> leaf_node = tree.nodes[node_id]
iex> NaryTree.is_leaf? leaf_node
true
Link to this function is_nary_tree?(arg1) View Source
is_nary_tree?(NaryTree.t()) :: boolean()

Check whether the argument is of NaryTree type.

Example

iex> NaryTree.is_nary_tree? NaryTree.new(NaryTree.Node.new "Node")
true

Check whether a node is a root node.

Example

iex> node = NaryTree.Node.new "Root node"
iex> NaryTree.is_root? node
true

Converts a list of nodes back into nodes map %{node1id => %NaryTree.Node{}, node2id => ...}

Link to this function merge(tree, branch, node_id) View Source

Merges a tree into another tree at the specified node point. Returns the resulting combined tree or :error if the specified node point doesn’t exist.

Example

iex> branch = NaryTree.Node.new("Branch Node")
iex> tree1 = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...>   NaryTree.add_child(branch)
iex> tree2 = NaryTree.new(NaryTree.Node.new("Subtree")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf"))
iex> combined = NaryTree.merge(tree1, tree2, branch.id)
iex> Enum.count combined.nodes
4
Link to this function move_nodes(tree, nodes, new_parent) View Source
move_nodes(NaryTree.t(), [NaryTree.Node.t()], NaryTree.Node.t()) :: NaryTree.t()
move_nodes(NaryTree.t(), [String.t()], String.t()) :: NaryTree.t()

Move children nodes from one node to another node.

Create a new, empty tree.

Example

iex> NaryTree.new()
%NaryTree{nodes: %{}, root: :empty}

Create a new tree with a root node.

Example

iex> %NaryTree{root: key, nodes: nodes} = NaryTree.new(NaryTree.Node.new "Root node")
iex> nodes[key].name
"Root node"

Returns the parent node of a tree, or :empty if there is none

Example

iex> branch = NaryTree.Node.new("Branch Node")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...>   NaryTree.add_child(branch)
iex> %NaryTree.Node{name: name} = NaryTree.root(tree)
iex> name
"Root Node"

Invoked to “pop” the specified node from the tree.

When key exists in the tree, it returns a {a_node, new_tree} tuple where a_node is the node that was under key and new_tree is the tree without a_node.

When key is not present in the tree, it returns {nil, tree}.

Link to this function put(tree, id, node_to_replace) View Source

Put a node into the tree at the specified id. Put will replace the name and content attributes of the node at id with the attributes of the new nodes. The children and parent of the old node will remain the same so that the hierarchy structure remains the same.

Example

iex> tree = NaryTree.new NaryTree.Node.new("Root")
iex> tree.nodes[tree.root].name
"Root"
iex> tree = NaryTree.put(tree, tree.root, NaryTree.Node.new("Node"))
iex> tree.nodes[tree.root].name
"Node"

Returns the root node of a tree.

Example

iex> tree = NaryTree.new(NaryTree.Node.new("Root Node"))
iex> %NaryTree.Node{name: name} = NaryTree.root(tree)
iex> name
"Root Node"

Returns the sibling nodes of a node.

Collects nodes of a tree by using depth-first traversal. Returns a list of NaryTree.Node structs

Link to this function to_map(tree, func \\ &attr/1) View Source

Converts a tree into a hierarchical map with children nodes embedded in an array.

Takes tree as argument, and an optional function. The function takes a node parameter and should return a map of attributes.

The default function returns %{id: node.id, name: node.name, content: node.content, level: node.level, parent: node.parent}

Example

iex> tree = NaryTree.new(NaryTree.Node.new("Root")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf 1")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf 2")) |>
...>   NaryTree.to_map( &(%{key: &1.name}) )
%{children: [%{key: "Leaf 1"}, %{key: "Leaf 2"}], key: "Root"}
Link to this function update_content(tree, func) View Source
update_content(NaryTree.t(), function()) :: NaryTree.t()

Enumerates tree nodes, and applies function to each node’s content. Returns updated tree, with new content for every nodes

Example

iex> tree = NaryTree.new(NaryTree.Node.new("Root node")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf node 1")) |>
...>   NaryTree.add_child(NaryTree.Node.new("Leaf node 2"))
iex> Enum.map tree.nodes, fn({_,node}) -> node.content end
[:empty, :empty, :empty]
iex> NaryTree.update_content(tree, fn(_) -> %{x: 4} end) |>
...>   Map.get(:nodes) |> Enum.map(fn({_,node}) -> node.content end)
[%{x: 4}, %{x: 4}, %{x: 4}]