modular_tree 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/modular_tree/algorithms.rb +30 -15
- data/lib/modular_tree/filter.rb +3 -2
- data/lib/modular_tree/implementations.rb +1 -0
- data/lib/modular_tree/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0900ab1e0482487fcb6b63c28fccb0d7dc7f71e5ce54230f3ee551ff67f0dfb5'
|
4
|
+
data.tar.gz: bf6b30a19df1fa8211b355bf06392dbefad2950a2a52bd494dad99605f392669
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52d2ea9f3c82c6e7578f50b51804c223d267b1757f0709776addf39752e1034a57b14354f6877236d12017f2368300c5f3064537a3592f2fcf72bd69e2f991de
|
7
|
+
data.tar.gz: ad298843f7e45b03654ef53b96c507cf51ee0219c01abc4f30619a9396b17c9e775b64fb10b4fa9d3a9bbce0232f7235e2de2e283632a1cba38690634b9c909b
|
@@ -77,6 +77,21 @@ module Tree
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
# Filter children. Doesn't recurse. If a block is given, it should return
|
81
|
+
# truish to select a child node
|
82
|
+
#
|
83
|
+
# TODO: Maybe make #children an Array extended with filtering
|
84
|
+
def choose(match_expr = nil, &block)
|
85
|
+
matcher = Matcher.new(match_expr, &block)
|
86
|
+
if block_given?
|
87
|
+
a = []
|
88
|
+
each_branch { |branch, key| a << branch if matcher.match? branch }
|
89
|
+
a
|
90
|
+
else
|
91
|
+
Enumerator.new { |enum| each_branch { |branch, key| enum << branch if matcher.match? branch } }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
80
95
|
# Like #each but the block is called with node, key, and parent instead of
|
81
96
|
# value, key, and parent
|
82
97
|
def nodes(*filter, this: true, &block) = common_each(*filter, :node, :do_each_preorder, this, &block)
|
@@ -89,9 +104,8 @@ module Tree
|
|
89
104
|
|
90
105
|
# Enumerator of edges in the tree. Edges are [previous-matching-node,
|
91
106
|
# matching-node] tuples. Top-level nodes have previous-matching-node set to
|
92
|
-
# nil
|
93
|
-
#
|
94
|
-
# FIXME: Not working right now. Not sure how #edges relates to #pairs
|
107
|
+
# nil. If the filter matches all nodes the value is an edge-representation
|
108
|
+
# of the tree
|
95
109
|
def edges(*filter, this: true, &block)
|
96
110
|
if block_given?
|
97
111
|
each(*filter, this: this) { |node, _, parent| yield parent, node }
|
@@ -100,6 +114,19 @@ module Tree
|
|
100
114
|
end
|
101
115
|
end
|
102
116
|
|
117
|
+
# Return array of [previous-matching-node, matching-node] tuples. Returns
|
118
|
+
# the empty array ff there is no matching set of nodes
|
119
|
+
def pairs(first_match_expr, second_match_expr, this: true)
|
120
|
+
first_matcher = Matcher.new(first_match_expr)
|
121
|
+
second_matcher = Matcher.new(second_match_expr)
|
122
|
+
or_matcher = first_matcher | second_matcher # avoids re-computing this value over and over
|
123
|
+
result = []
|
124
|
+
nodes(first_matcher, false, this: this) { |node|
|
125
|
+
node.do_pairs(result, first_matcher, or_matcher)
|
126
|
+
}
|
127
|
+
result
|
128
|
+
end
|
129
|
+
|
103
130
|
# Find nodes matching +filter+ and call +traverse_block+ with a node and a
|
104
131
|
# block argument. +traverse_block+ can recurse into children by calling the
|
105
132
|
# supplied inner block
|
@@ -117,18 +144,6 @@ module Tree
|
|
117
144
|
nodes(filter, this: this).map { |node| traverse_block.call(node, inner_block) }
|
118
145
|
end
|
119
146
|
|
120
|
-
# Return array of [previous-matching-node, matching-node] tuples
|
121
|
-
def pairs(first_matcher_expr, second_matcher_expr, this: true)
|
122
|
-
first_matcher = Matcher.new(first_matcher_expr)
|
123
|
-
second_matcher = Matcher.new(second_matcher_expr)
|
124
|
-
or_matcher = first_matcher | second_matcher # avoids re-computing this value over and over
|
125
|
-
result = []
|
126
|
-
nodes(first_matcher, false, this: this) { |node|
|
127
|
-
node.do_pairs(result, first_matcher, or_matcher)
|
128
|
-
}
|
129
|
-
result
|
130
|
-
end
|
131
|
-
|
132
147
|
# Traverse the tree top-down while accumulating information in an
|
133
148
|
# accumulator object. The block takes a [accumulator, node] tuple and is
|
134
149
|
# responsible for adding itself to the accumulator. The return value from
|
data/lib/modular_tree/filter.rb
CHANGED
@@ -22,7 +22,7 @@ module Tree
|
|
22
22
|
#
|
23
23
|
# when +traverse+ is
|
24
24
|
# true Traverse always. This is the default
|
25
|
-
# false Traverse only if select didn't match
|
25
|
+
# false Traverse only if select didn't match # TODO: Never traverse to be able to use filters on children
|
26
26
|
# nil Expects +select+ to be a Proc object that returns a [select,
|
27
27
|
# traverse] tuple of booleans
|
28
28
|
#
|
@@ -33,7 +33,7 @@ module Tree
|
|
33
33
|
# It is not an error if the method doesn't exists on the a given node but
|
34
34
|
# the node is not selected/traversed. If the expression is a class or an
|
35
35
|
# array of classes, a given node matches if it is an instance of one of the
|
36
|
-
# classes
|
36
|
+
# classes and their subclasses
|
37
37
|
#
|
38
38
|
# If a block is given, it is supposed to return a [select, traverse] tuple
|
39
39
|
# of booleans
|
@@ -42,6 +42,7 @@ module Tree
|
|
42
42
|
# enumerators that doesn't execute the filter unless the enumerator is
|
43
43
|
# evaluated
|
44
44
|
#
|
45
|
+
# TODO: Accept RegExp -> use to_s to match
|
45
46
|
def initialize(select_expr = nil, traverse_expr = nil, &block)
|
46
47
|
if select_expr.nil? && block_given?
|
47
48
|
@matcher = block
|
data/lib/modular_tree/version.rb
CHANGED