Class: KeyTree::Forest

Inherits:
Array
  • Object
show all
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

Methods included from MetaData

#meta_data, #with_meta_data

Class Method Details

.[](*contents) ⇒ Object



16
17
18
19
20
# File 'lib/key_tree/forest.rb', line 16

def self.[](*contents)
  contents.reduce(Forest.new) do |result, content|
    result << content.to_key_wood
  end
end

Instance Method Details

#[](key) ⇒ 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.



33
34
35
36
37
38
39
40
41
42
# File 'lib/key_tree/forest.rb', line 33

def [](key)
  return super(key) if key.is_a?(Numeric)

  trees.lazy.each do |tree|
    result = tree[key]
    return result unless result.nil?
    break if tree.prefix?(key)
  end
  nil
end

#fetch(key) ⇒ Object



44
45
46
47
48
49
# File 'lib/key_tree/forest.rb', line 44

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



77
78
79
80
81
# File 'lib/key_tree/forest.rb', line 77

def flatten(&merger)
  trees.reverse_each.reduce(Tree[]) do |result, tree|
    result.merge!(tree, &merger)
  end
end

#include?(needle) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
# File 'lib/key_tree/forest.rb', line 66

def include?(needle)
  case needle
  when Tree, Forest
    super(needle)
  else
    key_path?(needle)
  end
end

#key?(key) ⇒ Boolean Also known as: has_key?

Returns:

  • (Boolean)


51
52
53
# File 'lib/key_tree/forest.rb', line 51

def key?(key)
  trees.lazy.any? { |tree| tree.key?(key) }
end

#key_path?(key) ⇒ Boolean Also known as: has_key_path?

Returns:

  • (Boolean)


61
62
63
# File 'lib/key_tree/forest.rb', line 61

def key_path?(key)
  trees.lazy.any? { |tree| tree.key_path?(key) }
end

#key_pathsObject

Return all visible key paths in the forest



96
97
98
# File 'lib/key_tree/forest.rb', line 96

def key_paths
  trees.reduce(Set.new) { |result, tree| result.merge(tree.key_paths) }
end

#prefix?(key) ⇒ Boolean Also known as: has_prefix?

Returns:

  • (Boolean)


56
57
58
# File 'lib/key_tree/forest.rb', line 56

def prefix?(key)
  trees.lazy.any? { |tree| tree.prefix?(key) }
end

#treesObject

Return a breadth-first Enumerator for all the trees in the forest, and any nested forests



85
86
87
88
89
90
91
92
93
# File 'lib/key_tree/forest.rb', line 85

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