Class: Tree::TreeNode
- Inherits:
-
Object
- Object
- Tree::TreeNode
- Includes:
- Comparable, Enumerable, Utils::CamelCaseMethodHandler, Utils::HashConverter, Utils::JSONConverter, Utils::TreeMergeHandler, Utils::TreeMetricsHandler, Utils::TreePathHandler
- Defined in:
- lib/tree.rb
Overview
TreeNode Class Description
This class models the nodes for an N-ary tree data structure. The nodes are named, and have a place-holder for the node data (i.e., content of the node). The node names are required to be unique amongst the sibling/peer nodes. Note that the name is implicitly used as an ID within the data structure).
The node's content is not required to be unique across different nodes in the tree, and can be nil
as well.
The class provides various methods to navigate the tree, traverse the structure, modify contents of the node, change position of the node in the tree, and to make structural changes to the tree.
A node can have any number of child nodes attached to it and hence can be used to create N-ary trees. Access to the child nodes can be made in order (with the conventional left to right access), or randomly.
The node also provides direct access to its parent node as well as other superior parents in the path to root of the tree. In addition, a node can also access its sibling nodes, if present.
Note that while this implementation does not explicitly support directed graphs, the class itself makes no restrictions on associating a node's content with multiple nodes in the tree. However, having duplicate nodes within the structure is likely to cause unpredictable behavior.
Example
noinspection RubyTooManyMethodsInspection
Direct Known Subclasses
Core Attributes collapse
-
#content ⇒ Object
Content of this node.
-
#has_children? ⇒ Boolean
readonly
true
if the this node has any child node. -
#has_content? ⇒ Boolean
readonly
true
if this node has content. -
#is_leaf? ⇒ Boolean
readonly
true
if this node is a leaf - i.e., one without any children. -
#is_root? ⇒ Boolean
readonly
Returns
true
if this is a root node. -
#name ⇒ Object
readonly
Name of this node.
-
#parent ⇒ Object
readonly
Parent of this node.
-
#parentage ⇒ Array<Tree::TreeNode>?
readonly
An array of ancestors of this node in reversed order (the first element is the immediate parent of this node).
-
#root ⇒ Tree::TreeNode
readonly
Root node for the (sub)tree to which this node belongs.
Attributes included from Utils::TreeMetricsHandler
#breadth, #depth, #in_degree, #length, #level, #node_depth, #node_height, #out_degree, #size
Node Creation collapse
-
#detached_copy ⇒ Tree::TreeNode
Returns a copy of this node, with its parent and children links removed.
-
#detached_subtree_copy ⇒ Tree::TreeNode
(also: #dup)
Returns a copy of entire (sub-)tree from this node.
-
#initialize(name, content = nil) ⇒ TreeNode
constructor
Creates a new node with a name and optional content.
-
#marshal_dump ⇒ Object
Returns a marshal-dump representation of the (sub)tree rooted at this node.
-
#marshal_load(dumped_tree_array) ⇒ Object
Loads a marshaled dump of a tree and returns the root node of the reconstructed tree.
Structure Modification collapse
-
#<<(child) ⇒ Tree::TreeNode
Convenience synonym for #add method.
-
#add(child, at_index = -1)) ⇒ Tree::TreeNode
Adds the specified child node to this node.
-
#freeze_tree! ⇒ Object
Freezes all nodes in the (sub)tree rooted at this node.
-
#remove!(child) ⇒ Tree::TreeNode
Removes the specified child node from this node.
-
#remove_all! ⇒ Tree::TreeNode
Removes all children from this node.
-
#remove_from_parent! ⇒ Tree:TreeNode
Removes this node from its parent.
-
#rename(new_name) ⇒ Object
Renames the node and updates the parent's reference to it.
-
#rename_child(old_name, new_name) ⇒ Object
Renames the specified child node.
-
#replace!(old_child, new_child) ⇒ Tree::TreeNode
Replaces the specified child node with another child node on this node.
-
#replace_with(node) ⇒ Tree::TreeNode
Replaces the node with another node.
Tree Traversal collapse
-
#[](name_or_index, num_as_name = false) ⇒ Tree::TreeNode
Returns the requested node from the set of immediate children.
-
#breadth_each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Performs breadth-first traversal of the (sub)tree rooted at this node.
-
#children {|child| ... } ⇒ Tree::TreeNode+
An array of all the immediate children of this node.
-
#each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses each node (including this node) of the (sub)tree rooted at this node by yielding the nodes to the specified block.
-
#each_leaf(&block) {|node| ... } ⇒ Tree::TreeNode+
Yields every leaf node of the (sub)tree rooted at this node to the specified block.
-
#each_level {|level| ... } ⇒ Tree::TreeNode, Enumerator
Yields every level of the (sub)tree rooted at this node to the specified block.
-
#postordered_each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses the (sub)tree rooted at this node in post-ordered sequence.
-
#preordered_each {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses the (sub)tree rooted at this node in pre-ordered sequence.
Navigating the Child Nodes collapse
-
#first_child ⇒ Tree::TreeNode
First child of this node.
-
#last_child ⇒ Tree::TreeNode
Last child of this node.
Navigating the Sibling Nodes collapse
-
#first_sibling ⇒ Tree::TreeNode
First sibling of this node.
-
#is_first_sibling? ⇒ Boolean
Returns
true
if this node is the first sibling at its level. -
#is_last_sibling? ⇒ Boolean
Returns
true
if this node is the last sibling at its level. -
#is_only_child? ⇒ Boolean
true
if this node is the only child of its parent. -
#last_sibling ⇒ Tree::TreeNode
Last sibling of this node.
-
#next_sibling ⇒ Tree::treeNode
Next sibling for this node.
-
#previous_sibling ⇒ Tree::treeNode
Previous sibling of this node.
-
#siblings {|sibling| ... } ⇒ Array<Tree::TreeNode>, Tree::TreeNode
An array of siblings for this node.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer
Provides a comparison operation for the nodes.
-
#print_tree(level = self.node_depth, max_depth = nil, block = lambda { |node, prefix| puts "#{prefix} #{node.name}" }) ⇒ Object
Pretty prints the (sub)tree rooted at this node.
-
#to_s ⇒ String
Returns string representation of this node.
Methods included from Utils::HashConverter
#add_from_hash, included, #to_h
Methods included from Utils::TreeMergeHandler
Methods included from Utils::JSONConverter
Methods included from Utils::CamelCaseMethodHandler
Methods included from Utils::TreePathHandler
included, #path_as_array, #path_as_string
Methods included from Utils::TreeMetricsHandler
Constructor Details
#initialize(name, content = nil) ⇒ TreeNode
If the name is an Integer
, then the semantics of #[] access method can be surprising, as an Integer
parameter to that method normally acts as an index to the children array, and follows the zero-based indexing convention.
Creates a new node with a name and optional content. The node name is expected to be unique within the tree.
The content can be of any type, and defaults to nil
.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/tree.rb', line 218 def initialize(name, content = nil) raise ArgumentError, 'Node name HAS to be provided!' if name == nil @name, @content = name, content if name.kind_of?(Integer) warn StructuredWarnings::StandardWarning, 'Using integer as node name.'\ ' Semantics of TreeNode[] may not be what you expect!'\ " #{name} #{content}" end self.set_as_root! @children_hash = Hash.new @children = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Tree::Utils::CamelCaseMethodHandler
Instance Attribute Details
#content ⇒ Object
Content of this node. Can be nil
. Note that there is no uniqueness constraint related to this attribute.
123 124 125 |
# File 'lib/tree.rb', line 123 def content @content end |
#has_children? ⇒ Boolean (readonly)
true
if the this node has any child node.
194 195 196 |
# File 'lib/tree.rb', line 194 def has_children? @children.length != 0 end |
#has_content? ⇒ Boolean (readonly)
true
if this node has content.
153 154 155 |
# File 'lib/tree.rb', line 153 def has_content? @content != nil end |
#is_leaf? ⇒ Boolean (readonly)
true
if this node is a leaf - i.e., one without any children.
164 165 166 |
# File 'lib/tree.rb', line 164 def is_leaf? !has_children? end |
#is_root? ⇒ Boolean (readonly)
Returns true
if this is a root node. Note that orphaned children will also be reported as root nodes.
145 146 147 |
# File 'lib/tree.rb', line 145 def is_root? @parent.nil? end |
#name ⇒ Object
Name of this node. Expected to be unique within the tree.
Note that the name attribute really functions as an ID within the tree structure, and hence the uniqueness constraint is required.
This may be changed in the future, but for now it is best to retain unique names within the tree structure, and use the content
attribute for any non-unique node requirements.
If you want to change the name, you probably want to call rename
instead.
116 117 118 |
# File 'lib/tree.rb', line 116 def name @name end |
#parent ⇒ Object
Parent of this node. Will be nil
for a root node.
127 128 129 |
# File 'lib/tree.rb', line 127 def parent @parent end |
#parentage ⇒ Array<Tree::TreeNode>? (readonly)
An array of ancestors of this node in reversed order (the first element is the immediate parent of this node).
Returns nil
if this is a root node.
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/tree.rb', line 176 def parentage return nil if is_root? parentage_array = [] prev_parent = self.parent while prev_parent parentage_array << prev_parent prev_parent = prev_parent.parent end parentage_array end |
Instance Method Details
#<<(child) ⇒ Tree::TreeNode
Convenience synonym for #add method.
This method allows an easy mechanism to add node hierarchies to the tree on a given path via chaining the method calls to successive child nodes.
330 331 332 |
# File 'lib/tree.rb', line 330 def <<(child) add(child) end |
#<=>(other) ⇒ Integer
Provides a comparison operation for the nodes.
Comparison is based on the natural ordering of the node name objects.
954 955 956 957 |
# File 'lib/tree.rb', line 954 def <=>(other) return nil if other == nil || other.class != Tree::TreeNode self.name <=> other.name end |
#[](name_or_index, num_as_name = false) ⇒ Tree::TreeNode
The use of Integer
names is allowed by using the optional num_as_name
flag.
Returns the requested node from the set of immediate children.
-
If the
name
argument is an Integer, then the in-sequence array of children is accessed using the argument as the index (zero-based). However, if the second optionalnum_as_name
argument istrue
, then thename
is used literally as a name, and NOT as an index -
If the
name
argument is NOT an Integer, then it is taken to be the name of the child node to be returned.
If a non-Integer
name
is passed, and the num_as_name
parameter is also true
, then a warning is thrown (as this is a redundant use of the num_as_name
flag.)
603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
# File 'lib/tree.rb', line 603 def [](name_or_index, num_as_name=false) raise ArgumentError, 'Name_or_index needs to be provided!' if name_or_index == nil if name_or_index.kind_of?(Integer) and not num_as_name @children[name_or_index] else if num_as_name and not name_or_index.kind_of?(Integer) warn StructuredWarnings::StandardWarning, 'Redundant use of the `num_as_name` flag for non-integer node name' end @children_hash[name_or_index] end end |
#add(child, at_index = -1)) ⇒ Tree::TreeNode
Adds the specified child node to this node.
This method can also be used for grafting a subtree into this node's tree, if the specified child node is the root of a subtree (i.e., has child nodes under it).
this node becomes parent of the node passed in as the argument, and the child is added as the last child (“right most”) in the current set of children of this node.
Additionally you can specify a insert position. The new node will be inserted BEFORE that position. If you don't specify any position the node will be just appended. This feature is provided to make implementation of node movement within the tree very simple.
If an insertion position is provided, it needs to be within the valid range of:
-children.size..children.size
This is to prevent nil
nodes being created as children if a non-existent position is used.
If the new node being added has an existing parent node, then it will be removed from this pre-existing parent prior to being added as a child to this node. I.e., the child node will effectively be moved from its old parent to this node. In this situation, after the operation is complete, the node will no longer exist as a child for its old parent.
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/tree.rb', line 378 def add(child, at_index = -1) # Only handles the immediate child scenario raise ArgumentError, 'Attempting to add a nil node' unless child raise ArgumentError, 'Attempting add node to itself' if self.equal?(child) raise ArgumentError, 'Attempting add root as a child' if child.equal?(root) # Lazy mans unique test, won't test if children of child are unique in # this tree too. raise "Child #{child.name} already added!"\ if @children_hash.include?(child.name) child.parent.remove! child if child.parent # Detach from the old parent if insertion_range.include?(at_index) @children.insert(at_index, child) else raise 'Attempting to insert a child at a non-existent location'\ " (#{at_index}) "\ 'when only positions from '\ "#{insertion_range.min} to #{insertion_range.max} exist." end @children_hash[child.name] = child child.parent = self child end |
#breadth_each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Performs breadth-first traversal of the (sub)tree rooted at this node. The traversal at a given level is from left-to-right. this node itself is the first node to be traversed.
noinspection RubyUnusedLocalVariable
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
# File 'lib/tree.rb', line 714 def breadth_each(&block) return self.to_enum(:breadth_each) unless block_given? node_queue = [self] # Create a queue with self as the initial entry # Use a queue to do breadth traversal until node_queue.empty? node_to_traverse = node_queue.shift yield node_to_traverse # Enqueue the children from left to right. node_to_traverse.children { |child| node_queue.push child } end self if block_given? end |
#children {|child| ... } ⇒ Tree::TreeNode+
An array of all the immediate children of this node. The child nodes are ordered “left-to-right” in the returned array.
If a block is given, yields each child node to the block traversing from left to right.
742 743 744 745 746 747 748 749 |
# File 'lib/tree.rb', line 742 def children if block_given? @children.each {|child| yield child} self else @children.clone end end |
#detached_copy ⇒ Tree::TreeNode
Returns a copy of this node, with its parent and children links removed. The original node remains attached to its tree.
238 239 240 |
# File 'lib/tree.rb', line 238 def detached_copy self.class.new(@name, @content ? @content.clone : nil) end |
#detached_subtree_copy ⇒ Tree::TreeNode Also known as: dup
Returns a copy of entire (sub-)tree from this node.
248 249 250 251 252 |
# File 'lib/tree.rb', line 248 def detached_subtree_copy new_node = detached_copy children { |child| new_node << child.detached_subtree_copy } new_node end |
#each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses each node (including this node) of the (sub)tree rooted at this node by yielding the nodes to the specified block.
The traversal is depth-first and from left-to-right in pre-ordered sequence.
noinspection RubyUnusedLocalVariable
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
# File 'lib/tree.rb', line 633 def each(&block) # :yields: node return self.to_enum unless block_given? node_stack = [self] # Start with this node until node_stack.empty? current = node_stack.shift # Pop the top-most node if current # Might be 'nil' (esp. for binary trees) yield current # and process it # Stack children of the current node at top of the stack node_stack = current.children.concat(node_stack) end end self if block_given? end |
#each_leaf(&block) {|node| ... } ⇒ Tree::TreeNode+
Yields every leaf node of the (sub)tree rooted at this node to the specified block.
May yield this node as well if this is a leaf node. Leaf traversal is depth-first and left-to-right.
noinspection RubyUnusedLocalVariable
766 767 768 769 770 771 772 773 |
# File 'lib/tree.rb', line 766 def each_leaf(&block) if block_given? self.each { |node| yield(node) if node.is_leaf? } self else self.select { |node| node.is_leaf? } end end |
#each_level {|level| ... } ⇒ Tree::TreeNode, Enumerator
Yields every level of the (sub)tree rooted at this node to the specified block.
Will yield this node as well since it is considered the first level.
784 785 786 787 788 789 790 791 792 793 794 795 |
# File 'lib/tree.rb', line 784 def each_level &block if block_given? level = [self] until level.empty? yield level level = level.map(&:children).flatten end return self else self.each end end |
#first_child ⇒ Tree::TreeNode
First child of this node. Will be nil
if no children are present.
805 806 807 |
# File 'lib/tree.rb', line 805 def first_child @children.first end |
#first_sibling ⇒ Tree::TreeNode
First sibling of this node. If this is the root node, then returns itself.
'First' sibling is defined as follows:
- First sibling
-
The left-most child of this node's parent, which may be
this node itself
831 832 833 |
# File 'lib/tree.rb', line 831 def first_sibling is_root? ? self : parent.children.first end |
#freeze_tree! ⇒ Object
Freezes all nodes in the (sub)tree rooted at this node.
The nodes become immutable after this operation. In effect, the entire tree's structure and contents become read-only and cannot be changed.
562 563 564 |
# File 'lib/tree.rb', line 562 def freeze_tree! each {|node| node.freeze} end |
#is_first_sibling? ⇒ Boolean
Returns true
if this node is the first sibling at its level.
841 842 843 |
# File 'lib/tree.rb', line 841 def is_first_sibling? first_sibling == self end |
#is_last_sibling? ⇒ Boolean
Returns true
if this node is the last sibling at its level.
867 868 869 |
# File 'lib/tree.rb', line 867 def is_last_sibling? last_sibling == self end |
#is_only_child? ⇒ Boolean
true
if this node is the only child of its parent.
As a special case, a root node will always return true
.
905 906 907 |
# File 'lib/tree.rb', line 905 def is_only_child? is_root? ? true : parent.children.size == 1 end |
#last_child ⇒ Tree::TreeNode
Last child of this node. Will be nil
if no children are present.
813 814 815 |
# File 'lib/tree.rb', line 813 def last_child @children.last end |
#last_sibling ⇒ Tree::TreeNode
Last sibling of this node. If this is the root node, then returns itself.
'Last' sibling is defined as follows:
- Last sibling
-
The right-most child of this node's parent, which may be
this node itself
857 858 859 |
# File 'lib/tree.rb', line 857 def last_sibling is_root? ? self : parent.children.last end |
#marshal_dump ⇒ Object
Returns a marshal-dump representation of the (sub)tree rooted at this node.
262 263 264 |
# File 'lib/tree.rb', line 262 def marshal_dump self.collect { |node| node.create_dump_rep } end |
#marshal_load(dumped_tree_array) ⇒ Object
This method probably should be a class method. It currently clobbers self and makes itself the root.
Loads a marshaled dump of a tree and returns the root node of the reconstructed tree. See the Marshal class for additional details.
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/tree.rb', line 286 def marshal_load(dumped_tree_array) nodes = { } dumped_tree_array.each do |node_hash| name = node_hash[:name] parent_name = node_hash[:parent] content = Marshal.load(node_hash[:content]) if parent_name nodes[name] = current_node = Tree::TreeNode.new(name, content) nodes[parent_name].add current_node else # This is the root node, hence initialize self. initialize(name, content) nodes[name] = self # Add self to the list of nodes end end end |
#next_sibling ⇒ Tree::treeNode
Next sibling for this node. The next node is defined as the node to right of this node.
Will return nil
if no subsequent node is present, or if this is a root node.
919 920 921 922 923 924 |
# File 'lib/tree.rb', line 919 def next_sibling return nil if is_root? idx = parent.children.index(self) parent.children.at(idx + 1) if idx end |
#postordered_each(&block) {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses the (sub)tree rooted at this node in post-ordered sequence.
noinspection RubyUnusedLocalVariable
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/tree.rb', line 675 def postordered_each(&block) return self.to_enum(:postordered_each) unless block_given? # Using a marked node in order to skip adding the children of nodes that # have already been visited. This allows the stack depth to be controlled, # and also allows stateful backtracking. marked_node = Struct.new(:node, :visited) node_stack = [marked_node.new(self, false)] # Start with self until node_stack.empty? peek_node = node_stack[0] if peek_node.node.has_children? and not peek_node.visited peek_node.visited = true # Add the children to the stack. Use the marking structure. marked_children = peek_node.node.children.map {|node| marked_node.new(node, false)} node_stack = marked_children.concat(node_stack) next else yield node_stack.shift.node # Pop and yield the current node end end self if block_given? end |
#preordered_each {|node| ... } ⇒ Tree::TreeNode, Enumerator
Traverses the (sub)tree rooted at this node in pre-ordered sequence. This is a synonym of #each.
661 662 663 |
# File 'lib/tree.rb', line 661 def preordered_each(&block) # :yields: node each(&block) end |
#previous_sibling ⇒ Tree::treeNode
Previous sibling of this node. Previous node is defined to be the node to left of this node.
Will return nil
if no predecessor node is present, or if this is a root node.
936 937 938 939 940 941 |
# File 'lib/tree.rb', line 936 def previous_sibling return nil if is_root? idx = parent.children.index(self) parent.children.at(idx - 1) if idx && idx > 0 end |
#print_tree(level = self.node_depth, max_depth = nil, block = lambda { |node, prefix| puts "#{prefix} #{node.name}" }) ⇒ Object
Pretty prints the (sub)tree rooted at this node.
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 |
# File 'lib/tree.rb', line 965 def print_tree(level = self.node_depth, max_depth = nil, block = lambda { |node, prefix| puts "#{prefix} #{node.name}" }) prefix = '' if is_root? prefix << '*' else prefix << '|' unless parent.is_last_sibling? prefix << (' ' * (level - 1) * 4) prefix << (is_last_sibling? ? '+' : '|') prefix << '---' prefix << (has_children? ? '+' : '>') end block.call(self, prefix) # Exit if the max level is defined, and reached. return unless max_depth.nil? || level < max_depth children { |child| child.print_tree(level + 1, max_depth, block) if child } # Child might be 'nil' end |
#remove!(child) ⇒ Tree::TreeNode
Removes the specified child node from this node.
This method can also be used for pruning a sub-tree, in cases where the removed child node is the root of the sub-tree to be pruned.
The removed child node is orphaned but accessible if an alternate reference exists. If accessible via an alternate reference, the removed child will report itself as a root node for its sub-tree.
498 499 500 501 502 503 504 505 |
# File 'lib/tree.rb', line 498 def remove!(child) return nil unless child @children_hash.delete(child.name) @children.delete(child) child.set_as_root! child end |
#remove_all! ⇒ Tree::TreeNode
Removes all children from this node. If an independent reference exists to the child nodes, then these child nodes report themselves as roots after this operation.
541 542 543 544 545 546 547 |
# File 'lib/tree.rb', line 541 def remove_all! @children.each { |child| child.set_as_root! } @children_hash.clear @children.clear self end |
#remove_from_parent! ⇒ Tree:TreeNode
Removes this node from its parent. This node becomes the new root for its subtree.
If this is the root node, then does nothing.
529 530 531 |
# File 'lib/tree.rb', line 529 def remove_from_parent! @parent.remove!(self) unless is_root? end |
#rename(new_name) ⇒ Object
Renames the node and updates the parent's reference to it
423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/tree.rb', line 423 def rename(new_name) old_name = @name if is_root? self.name=(new_name) else @parent.rename_child old_name, new_name end old_name end |
#rename_child(old_name, new_name) ⇒ Object
Renames the specified child node
442 443 444 445 446 447 448 |
# File 'lib/tree.rb', line 442 def rename_child(old_name, new_name) raise ArgumentError, "Invalid child name specified: #{old_name}"\ unless @children_hash.has_key?(old_name) @children_hash[new_name] = @children_hash.delete(old_name) @children_hash[new_name].name=(new_name) end |
#replace!(old_child, new_child) ⇒ Tree::TreeNode
Replaces the specified child node with another child node on this node.
466 467 468 469 470 471 472 473 |
# File 'lib/tree.rb', line 466 def replace!(old_child, new_child) child_index = @children.find_index(old_child) old_child = remove! old_child add new_child, child_index old_child end |
#replace_with(node) ⇒ Tree::TreeNode
Replaces the node with another node
480 481 482 |
# File 'lib/tree.rb', line 480 def replace_with(node) @parent.replace!(self, node) end |
#siblings {|sibling| ... } ⇒ Array<Tree::TreeNode>, Tree::TreeNode
An array of siblings for this node. This node is excluded.
If a block is provided, yields each of the sibling nodes to the block. The root always has nil
siblings.
885 886 887 888 889 890 891 892 893 894 895 896 |
# File 'lib/tree.rb', line 885 def siblings if block_given? parent.children.each { |sibling| yield sibling if sibling != self } self else return [] if is_root? siblings = [] parent.children {|my_sibling| siblings << my_sibling if my_sibling != self} siblings end end |
#to_s ⇒ String
Returns string representation of this node. This method is primarily meant for debugging purposes.
311 312 313 |
# File 'lib/tree.rb', line 311 def to_s "Node Name: #{@name} Content: #{(@content.to_s || '<Empty>')} Parent: #{(is_root? ? '<None>' : @parent.name.to_s)} Children: #{@children.length} Total Nodes: #{size}" end |