modular_tree 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/modular_tree/algorithms.rb +12 -2
- data/lib/modular_tree/filter.rb +9 -6
- data/lib/modular_tree/implementations.rb +51 -1
- data/lib/modular_tree/properties.rb +4 -0
- data/lib/modular_tree/version.rb +1 -1
- data/lib/modular_tree.rb +2 -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: 1b145f3b7daeb0bddc2a2415e3a98d6d6232d95afeca8147908bffa2089ff412
|
4
|
+
data.tar.gz: 68271887a655b0196e5f9819f72ee80ca9e853c15568ab48cc1d7e15c4a29d22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9a39254ef102c23dbba9445b5b95b3d925d0954ef28de91107318c24ce9c450dd1fc2612cae18fc2c4033314bcd85b14a7126eb09e01daee076e380b05fe54c
|
7
|
+
data.tar.gz: 3b84c591c7816199835041074b6fb8b9506c5b85b438000045ce4d21627559835edeadf0336ca6635d76cef563082254318a1cf13d15342c431f407f51868615
|
@@ -63,11 +63,21 @@ module Tree
|
|
63
63
|
# Implementation of Enumerable#each extended with filters. The block is
|
64
64
|
# called with value, key, and parent as arguments (it may choose to
|
65
65
|
# ignore key and/or parent). Returns an enumerator of values without a block
|
66
|
-
def each(*filter, this: true, &block) = common_each(*filter, :value, :
|
66
|
+
def each(*filter, this: true, &block) = common_each(*filter, :value, :do_each_preorder, this, &block)
|
67
|
+
|
68
|
+
# Implementation of Enumerable#select extended with a single filter. As
|
69
|
+
# #each, the block is called with value, key, and parent arguments
|
70
|
+
def select(filter = nil, this: true, &block)
|
71
|
+
if block_given?
|
72
|
+
each(block, true, this: this).to_a
|
73
|
+
else
|
74
|
+
each(filter || true, true, this: this)
|
75
|
+
end
|
76
|
+
end
|
67
77
|
|
68
78
|
# Like #each but the block is called with node, key, and parent instead of
|
69
79
|
# value, key, and parent
|
70
|
-
def nodes(*filter, this: true, &block) = common_each(*filter, :node, :
|
80
|
+
def nodes(*filter, this: true, &block) = common_each(*filter, :node, :do_each_preorder, this, &block)
|
71
81
|
|
72
82
|
# Pre-order enumerator of selected nodes. Same as #each without a block
|
73
83
|
def preorder(*filter, this: true) = each(*filter, this: this)
|
data/lib/modular_tree/filter.rb
CHANGED
@@ -6,9 +6,9 @@ module Tree
|
|
6
6
|
# traverse expression decides if the child nodes should be traversed
|
7
7
|
# recursively
|
8
8
|
#
|
9
|
-
# The expressions can be a Proc, Symbol, or an array of classes. In
|
10
|
-
# addition, +select+ can
|
11
|
-
#
|
9
|
+
# The expressions can be a Proc, Symbol, Class, or an array of classes. In
|
10
|
+
# addition, +select+ can be true, and +traverse+ can be true, false, or
|
11
|
+
# nil. These values have special meanings:
|
12
12
|
#
|
13
13
|
# when +select+ is
|
14
14
|
# true Select always. This is the default
|
@@ -17,14 +17,17 @@ module Tree
|
|
17
17
|
# true Traverse always. This is the default
|
18
18
|
# false Traverse only if select didn't match
|
19
19
|
# nil Expects +select+ to return a two-tuple of booleans. Can't be
|
20
|
-
# used when +select+ is true
|
20
|
+
# used when +select+ is true. TODO: Explain
|
21
21
|
#
|
22
22
|
# If the expression is a Proc object, it will be called with the current
|
23
23
|
# node as argument. If the return value is true, the node is
|
24
24
|
# selected/traversed and skipped otherwise. If the expression is a method
|
25
25
|
# name (Symbol), the method will be called on each node with no arguments.
|
26
|
-
# It is not an error if the method doesn't exists
|
27
|
-
# selected/traversed
|
26
|
+
# It is not an error if the method doesn't exists on the a given node but
|
27
|
+
# the node is not selected/traversed
|
28
|
+
#
|
29
|
+
# If the expression is a class or an array of classes, a given node matches
|
30
|
+
# if it is an instance of one of the classes or any subclass
|
28
31
|
#
|
29
32
|
# Filters should not have side-effects because they can be used in
|
30
33
|
# enumerators that doesn't execute the filter unless the enumerator is
|
@@ -69,7 +69,7 @@ module Tree
|
|
69
69
|
|
70
70
|
def node = array
|
71
71
|
def this = array.first
|
72
|
-
def value = array.first
|
72
|
+
def value = array.first # FIXME What is this? It is a problem several places
|
73
73
|
|
74
74
|
attr_accessor :array
|
75
75
|
|
@@ -167,6 +167,33 @@ module Tree
|
|
167
167
|
|
168
168
|
def each_child(&block) = @children.map(&block)
|
169
169
|
def attach(child) = @children << child
|
170
|
+
|
171
|
+
# Can be used with any array implementation
|
172
|
+
def insert(where, child) = insert_append(:insert, where, child)
|
173
|
+
def append(where, child) = insert_append(:append, where, child)
|
174
|
+
|
175
|
+
def replace(where, *children)
|
176
|
+
children = Array(children).flatten
|
177
|
+
case where
|
178
|
+
when Integer
|
179
|
+
subject = @children[where] or raise ArgumentError
|
180
|
+
index = where
|
181
|
+
else
|
182
|
+
subject = where
|
183
|
+
index = @children.index(where) or raise ArgumentError
|
184
|
+
end
|
185
|
+
@children = @children[0...index] + children + @children[index + 1..-1]
|
186
|
+
subject
|
187
|
+
end
|
188
|
+
|
189
|
+
protected
|
190
|
+
def insert_append(which, where, child)
|
191
|
+
if !where.is_a?(Integer)
|
192
|
+
where = @children.index(where) or raise ArgumentError, "Can't find object"
|
193
|
+
end
|
194
|
+
where += 1 if which == :append
|
195
|
+
@children.insert(where, child)
|
196
|
+
end
|
170
197
|
end
|
171
198
|
|
172
199
|
module InternalChildrenHashImplementation
|
@@ -198,5 +225,28 @@ module Tree
|
|
198
225
|
child.send(:parent=, self)
|
199
226
|
end
|
200
227
|
end
|
228
|
+
|
229
|
+
module InternalParentChildArrayImplementation
|
230
|
+
include InternalParentChildImplementation
|
231
|
+
|
232
|
+
def insert(where, child)
|
233
|
+
super
|
234
|
+
child.send(:parent=, self)
|
235
|
+
end
|
236
|
+
|
237
|
+
def append(where, child)
|
238
|
+
super
|
239
|
+
child.send(:parent=, self)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Requires that Child classes already has defined this
|
243
|
+
def replace(where, *children)
|
244
|
+
children = Array(children).flatten
|
245
|
+
subject = super(where, children)
|
246
|
+
subject.send(:parent=, nil)
|
247
|
+
children.each { |child| child.send(:parent=, self) }
|
248
|
+
subject
|
249
|
+
end
|
250
|
+
end
|
201
251
|
end
|
202
252
|
|
data/lib/modular_tree/version.rb
CHANGED
data/lib/modular_tree.rb
CHANGED
@@ -39,9 +39,10 @@ module Tree
|
|
39
39
|
class ArrayTree < AbstractTree # Aka. SetTree aka. Tree
|
40
40
|
include InternalParentImplementation
|
41
41
|
include InternalChildrenArrayImplementation
|
42
|
-
include
|
42
|
+
include InternalParentChildArrayImplementation
|
43
43
|
include UpTreeAlgorithms
|
44
44
|
include DownTreeAlgorithms
|
45
|
+
include DownTreeFilteredAlgorithms
|
45
46
|
|
46
47
|
def self.filter(*args) = DownTreeAlgorithms.filter(*args)
|
47
48
|
end
|