Class: KeyTree::Forest
- Inherits:
-
Array
- Object
- Array
- KeyTree::Forest
- Includes:
- MetaData
- Defined in:
- lib/key_tree/forest.rb
Overview
A forest is a (possibly nested) collection of trees
Class Method Summary collapse
Instance Method Summary collapse
-
#[](key, &merger) ⇒ Object
For a numeric key, return the n:th tree in the forest.
- #fetch(key) ⇒ Object
-
#flatten(&merger) ⇒ Object
Flattening a forest produces a tree with the equivalent view of key paths.
- #key?(key) ⇒ Boolean
- #prefix?(key) ⇒ Boolean
- #tree_with_key(key) ⇒ Object
-
#trees ⇒ Object
Return a breadth-first Enumerator for all the trees in the forest, and any nested forests.
- #trees_with_key(key) ⇒ Object
Methods included from MetaData
Class Method Details
.[](*contents) ⇒ Object
11 12 13 14 15 |
# File 'lib/key_tree/forest.rb', line 11 def self.[](*contents) contents.reduce(Forest.new) do |result, content| result << KeyTree[content] end end |
Instance Method Details
#[](key, &merger) ⇒ Object
For a numeric key, return the n:th tree in the forest
For a key path convertable key, return the closest match in the forest
When a closer tree contains a prefix of the key, this shadows any key path matches in trees further away, returning nil. This preserves the constraints that only leaves may contain a value.
25 26 27 28 29 30 |
# File 'lib/key_tree/forest.rb', line 25 def [](key, &merger) return super(key) if key.is_a?(Numeric) fetch(key, &merger) rescue KeyError nil end |
#fetch(key) ⇒ Object
32 33 34 35 36 37 |
# File 'lib/key_tree/forest.rb', line 32 def fetch(key) return tree_with_key(key).fetch(key) unless block_given? values = trees_with_key(key).map { |tree| tree.fetch(key) } values.reverse.reduce { |left, right| yield(key, left, right) } end |
#flatten(&merger) ⇒ Object
Flattening a forest produces a tree with the equivalent view of key paths
60 61 62 63 64 |
# File 'lib/key_tree/forest.rb', line 60 def flatten(&merger) trees.reverse_each.reduce(Tree[]) do |result, tree| result.merge!(tree, &merger) end end |
#key?(key) ⇒ Boolean
50 51 52 |
# File 'lib/key_tree/forest.rb', line 50 def key?(key) trees.any? { |tree| tree.key?(key) } end |
#prefix?(key) ⇒ Boolean
54 55 56 |
# File 'lib/key_tree/forest.rb', line 54 def prefix?(key) trees.any? { |tree_or_forest| tree_or_forest.prefix?(key) } end |
#tree_with_key(key) ⇒ Object
39 40 41 42 |
# File 'lib/key_tree/forest.rb', line 39 def tree_with_key(key) result = trees.detect { |tree| tree.prefix?(key) } result || raise(KeyError, "key not found: #{key}") end |
#trees ⇒ Object
Return a breadth-first Enumerator for all the trees in the forest, and any nested forests
68 69 70 71 72 73 74 75 76 |
# File 'lib/key_tree/forest.rb', line 68 def trees Enumerator.new do |yielder| remaining = [self] remaining.each do |woods| next yielder << woods if woods.is_a?(Tree) woods.each { |wood| remaining << wood } end end end |
#trees_with_key(key) ⇒ Object
44 45 46 47 48 |
# File 'lib/key_tree/forest.rb', line 44 def trees_with_key(key) result = trees.select { |tree| tree.prefix?(key) } raise(KeyError, "key not found: #{key}") if result.empty? result end |