rubytree 0.9.4 → 0.9.5pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +12 -10
- data/History.rdoc +12 -0
- data/README.md +1 -0
- data/TAGS +242 -0
- data/TODO.org +15 -9
- data/lib/tree.rb +43 -11
- data/lib/tree/binarytree.rb +33 -1
- data/lib/tree/tree_deps.rb +1 -0
- data/lib/tree/utils/hash_converter.rb +161 -0
- data/lib/tree/utils/json_converter.rb +4 -4
- data/lib/tree/version.rb +1 -1
- data/test/test_binarytree.rb +67 -0
- data/test/test_tree.rb +239 -8
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93e0fdbd846f7fada7cd50d0e0ab414834f464dc
|
4
|
+
data.tar.gz: 3e70254cbc163580c3b7e40a497292a8e4d15128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 957a7cdbb556f41f9c599f82483f058e72cf432837a73bf71d1c86a26c0a3f1c2e1d3a8706a419d1c057b46920215ba2b9046bd83f10720efe46f3bb29bb2486
|
7
|
+
data.tar.gz: e74fb819ae9e568a1d5409f98ae89c18e0bd85f98300df7cc272dbfa9a7c4f01aa1d9474a8bc7fbb0f334019e3b045e2313621f16b2276aaf206bec24f241c6e
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubytree (0.9.
|
4
|
+
rubytree (0.9.5pre)
|
5
5
|
json (~> 1.8)
|
6
6
|
structured_warnings (~> 0.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
coveralls (0.7.
|
11
|
+
coveralls (0.7.1)
|
12
12
|
multi_json (~> 1.3)
|
13
13
|
rest-client
|
14
14
|
simplecov (>= 0.7)
|
@@ -16,27 +16,29 @@ GEM
|
|
16
16
|
thor
|
17
17
|
docile (1.1.5)
|
18
18
|
json (1.8.1)
|
19
|
-
mime-types (2.3)
|
19
|
+
mime-types (2.4.3)
|
20
20
|
multi_json (1.10.1)
|
21
|
+
netrc (0.8.0)
|
21
22
|
rake (10.3.2)
|
22
|
-
rdoc (4.1.
|
23
|
+
rdoc (4.1.2)
|
23
24
|
json (~> 1.4)
|
24
|
-
rest-client (1.
|
25
|
-
mime-types (>= 1.16)
|
25
|
+
rest-client (1.7.2)
|
26
|
+
mime-types (>= 1.16, < 3.0)
|
27
|
+
netrc (~> 0.7)
|
26
28
|
rtags (0.98)
|
27
29
|
rtagstask (0.0.4)
|
28
30
|
rtags (> 0.0.0)
|
29
|
-
simplecov (0.
|
31
|
+
simplecov (0.9.1)
|
30
32
|
docile (~> 1.1.0)
|
31
|
-
multi_json
|
33
|
+
multi_json (~> 1.0)
|
32
34
|
simplecov-html (~> 0.8.0)
|
33
35
|
simplecov-html (0.8.0)
|
34
36
|
structured_warnings (0.1.4)
|
35
37
|
term-ansicolor (1.3.0)
|
36
38
|
tins (~> 1.0)
|
37
39
|
thor (0.19.1)
|
38
|
-
tins (1.3.
|
39
|
-
yard (0.8.7.
|
40
|
+
tins (1.3.3)
|
41
|
+
yard (0.8.7.6)
|
40
42
|
|
41
43
|
PLATFORMS
|
42
44
|
ruby
|
data/History.rdoc
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
= History of Changes
|
4
4
|
|
5
|
+
=== 0.9.5pre / 2014-11-01
|
6
|
+
|
7
|
+
* Fixed {issue 13}[https://github.com/evolve75/RubyTree/issues/13] with the
|
8
|
+
patch provided by {Jen Hamon}[http://www.github.com/jhamon].
|
9
|
+
|
10
|
+
* Fixed a bug in {Tree::TreeNode#print_tree} with the patch provided by
|
11
|
+
{https://github.com/packetmonkey Evan Sharp}.
|
12
|
+
|
13
|
+
* Fixed {issue 31}[https://github.com/evolve75/RubyTree/issues/31], which was
|
14
|
+
causing incorrect behavior n {Tree::TreeNode#postordered_each} and
|
15
|
+
{Tree::TreeNode#breadth_each} methods when a block was not provided.
|
16
|
+
|
5
17
|
=== 0.9.4 / 2014-07-04
|
6
18
|
|
7
19
|
* Changed all references to {http://rubyforge.org}.
|
data/README.md
CHANGED
@@ -210,6 +210,7 @@ A big thanks to the following contributors for helping improve **RubyTree**:
|
|
210
210
|
duplicate node names in the tree (globally unique names).
|
211
211
|
6. [Paul de Courcel](https://github.com/pdecourcel) for adding the
|
212
212
|
`postordered_each` method.
|
213
|
+
7. [Jen Hamon](http://www.github.com/jhamon) for adding the `from_hash` method.
|
213
214
|
|
214
215
|
## LICENSE: ##
|
215
216
|
|
data/TAGS
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
|
2
|
+
lib/rubytree.rb,0
|
3
|
+
|
4
|
+
lib/tree/binarytree.rb,795
|
5
|
+
module Tree::Tree43,1906
|
6
|
+
class BinaryTreeNode::Tree::BinaryTreeNode52,2215
|
7
|
+
def left_child::Tree::BinaryTreeNode#left_child62,2498
|
8
|
+
def right_child::Tree::BinaryTreeNode#right_child74,2889
|
9
|
+
def is_left_child?::Tree::BinaryTreeNode#is_left_child?83,3165
|
10
|
+
def is_right_child?::Tree::BinaryTreeNode#is_right_child?93,3496
|
11
|
+
def add::Tree::BinaryTreeNode#add110,4153
|
12
|
+
def add_from_hash::Tree::BinaryTreeNode#add_from_hash143,5539
|
13
|
+
def inordered_each::Tree::BinaryTreeNode#inordered_each160,6096
|
14
|
+
def set_child_at::Tree::BinaryTreeNode#set_child_at191,7032
|
15
|
+
def left_child=::Tree::BinaryTreeNode#left_child=210,7700
|
16
|
+
def right_child=::Tree::BinaryTreeNode#right_child=222,8069
|
17
|
+
def swap_children::Tree::BinaryTreeNode#swap_children227,8215
|
18
|
+
|
19
|
+
lib/tree/tree_deps.rb,0
|
20
|
+
|
21
|
+
lib/tree/utils/camel_case_method_handler.rb,324
|
22
|
+
module Tree::Tree41,1848
|
23
|
+
module CamelCaseMethodHandler::Tree::CamelCaseMethodHandler44,2004
|
24
|
+
def self.included::Tree::CamelCaseMethodHandler.included45,2038
|
25
|
+
def method_missing::Tree::CamelCaseMethodHandler#method_missing49,2186
|
26
|
+
def to_snake_case::Tree::CamelCaseMethodHandler#to_snake_case66,2798
|
27
|
+
|
28
|
+
lib/tree/utils/hash_converter.rb,265
|
29
|
+
module Tree::Tree40,1916
|
30
|
+
def self.included::Tree.included42,1953
|
31
|
+
module ClassMethods::Tree::ClassMethods49,2177
|
32
|
+
def from_hash::Tree::ClassMethods#from_hash86,3823
|
33
|
+
def add_from_hash::Tree#add_from_hash129,5519
|
34
|
+
def to_h::Tree#to_h151,6367
|
35
|
+
|
36
|
+
lib/tree/utils/json_converter.rb,258
|
37
|
+
module Tree::Tree42,1925
|
38
|
+
def self.included::Tree.included44,1962
|
39
|
+
def as_json::Tree#as_json61,2413
|
40
|
+
def to_json::Tree#to_json89,3121
|
41
|
+
module ClassMethods::Tree::ClassMethods94,3271
|
42
|
+
def json_create::Tree::ClassMethods#json_create113,3986
|
43
|
+
|
44
|
+
lib/tree/utils/metrics_methods.rb,718
|
45
|
+
module Tree::Tree41,1833
|
46
|
+
module TreeMetricsHandler::Tree::TreeMetricsHandler43,1918
|
47
|
+
def self.included::Tree::TreeMetricsHandler.included44,1948
|
48
|
+
def size::Tree::TreeMetricsHandler#size56,2317
|
49
|
+
def length::Tree::TreeMetricsHandler#length67,2661
|
50
|
+
def node_height::Tree::TreeMetricsHandler#node_height80,3078
|
51
|
+
def node_depth::Tree::TreeMetricsHandler#node_depth96,3689
|
52
|
+
def level::Tree::TreeMetricsHandler#level105,3875
|
53
|
+
def depth::Tree::TreeMetricsHandler#depth124,4560
|
54
|
+
def breadth::Tree::TreeMetricsHandler#breadth140,5197
|
55
|
+
def in_degree::Tree::TreeMetricsHandler#in_degree154,5660
|
56
|
+
def out_degree::Tree::TreeMetricsHandler#out_degree165,5973
|
57
|
+
|
58
|
+
lib/tree/utils/tree_merge_handler.rb,214
|
59
|
+
module Tree::Tree40,1769
|
60
|
+
def merge::Tree#merge57,2500
|
61
|
+
def merge!::Tree#merge!72,3134
|
62
|
+
def check_merge_prerequisites::Tree#check_merge_prerequisites85,3441
|
63
|
+
def merge_trees::Tree#merge_trees102,4086
|
64
|
+
|
65
|
+
lib/tree/utils/utils.rb,27
|
66
|
+
module Tree::Tree39,1838
|
67
|
+
|
68
|
+
lib/tree/version.rb,27
|
69
|
+
module Tree::Tree38,1723
|
70
|
+
|
71
|
+
lib/tree.rb,2790
|
72
|
+
module Tree::Tree48,2158
|
73
|
+
class TreeNode::Tree::TreeNode85,3731
|
74
|
+
attr_reader :name::Tree::TreeNode#name109,4522
|
75
|
+
attr_accessor :content::Tree::TreeNode#content116,4721
|
76
|
+
attr_reader :parent::Tree::TreeNode#parent120,4837
|
77
|
+
def root::Tree::TreeNode#root127,5049
|
78
|
+
def is_root?::Tree::TreeNode#is_root?138,5355
|
79
|
+
def has_content?::Tree::TreeNode#has_content?146,5538
|
80
|
+
def is_leaf?::Tree::TreeNode#is_leaf?157,5792
|
81
|
+
def parentage::Tree::TreeNode#parentage169,6167
|
82
|
+
def has_children?::Tree::TreeNode#has_children?187,6593
|
83
|
+
def initialize::Tree::TreeNode#Tree::TreeNode.new210,7419
|
84
|
+
def detached_copy::Tree::TreeNode#detached_copy228,8036
|
85
|
+
def detached_subtree_copy::Tree::TreeNode#detached_subtree_copy238,8322
|
86
|
+
alias :dup::Tree::TreeNode#dup247,8583
|
87
|
+
def marshal_dump::Tree::TreeNode#marshal_dump252,8761
|
88
|
+
def create_dump_rep::Tree::TreeNode#create_dump_rep258,8929
|
89
|
+
def marshal_load::Tree::TreeNode#marshal_load273,9467
|
90
|
+
def to_s::Tree::TreeNode#to_s298,10251
|
91
|
+
def <<::Tree::TreeNode#<<321,11022
|
92
|
+
def add::Tree::TreeNode#add356,12550
|
93
|
+
def insertion_range::Tree::TreeNode#insertion_range376,13512
|
94
|
+
def replace!::Tree::TreeNode#replace!391,13930
|
95
|
+
def replace_with::Tree::TreeNode#replace_with405,14303
|
96
|
+
def remove!::Tree::TreeNode#remove!423,15035
|
97
|
+
def parent=::Tree::TreeNode#parent=438,15438
|
98
|
+
def remove_from_parent!::Tree::TreeNode#remove_from_parent!451,15823
|
99
|
+
def remove_all!::Tree::TreeNode#remove_all!462,16195
|
100
|
+
def set_as_root!::Tree::TreeNode#set_as_root!473,16424
|
101
|
+
def freeze_tree!::Tree::TreeNode#freeze_tree!483,16750
|
102
|
+
def []::Tree::TreeNode#[]523,18268
|
103
|
+
def each::Tree::TreeNode#each548,19235
|
104
|
+
def preordered_each::Tree::TreeNode#preordered_each576,20195
|
105
|
+
def postordered_each::Tree::TreeNode#postordered_each588,20607
|
106
|
+
def breadth_each::Tree::TreeNode#breadth_each624,22052
|
107
|
+
def children::Tree::TreeNode#children650,23005
|
108
|
+
def each_leaf::Tree::TreeNode#each_leaf671,23626
|
109
|
+
def first_child::Tree::TreeNode#first_child688,24048
|
110
|
+
def last_child::Tree::TreeNode#last_child696,24259
|
111
|
+
def first_sibling::Tree::TreeNode#first_sibling712,24706
|
112
|
+
def is_first_sibling?::Tree::TreeNode#is_first_sibling?722,24980
|
113
|
+
def last_sibling::Tree::TreeNode#last_sibling736,25396
|
114
|
+
def is_last_sibling?::Tree::TreeNode#is_last_sibling?746,25666
|
115
|
+
def siblings::Tree::TreeNode#siblings762,26219
|
116
|
+
def is_only_child?::Tree::TreeNode#is_only_child?781,26771
|
117
|
+
def next_sibling::Tree::TreeNode#next_sibling794,27174
|
118
|
+
def previous_sibling::Tree::TreeNode#previous_sibling810,27648
|
119
|
+
def <=>::Tree::TreeNode#<=>826,28159
|
120
|
+
def print_tree::Tree::TreeNode#print_tree836,28539
|
121
|
+
|
122
|
+
test/run_test.rb,0
|
123
|
+
|
124
|
+
test/test_binarytree.rb,1361
|
125
|
+
module TestTree::TestTree39,1717
|
126
|
+
class TestBinaryTreeNode::TestTree::TestBinaryTreeNode41,1776
|
127
|
+
def setup::TestTree::TestBinaryTreeNode#setup44,1868
|
128
|
+
def teardown::TestTree::TestBinaryTreeNode#teardown52,2171
|
129
|
+
def test_initialize::TestTree::TestBinaryTreeNode#test_initialize59,2330
|
130
|
+
def test_from_hash::TestTree::TestBinaryTreeNode#test_from_hash66,2692
|
131
|
+
def test_add_from_hash::TestTree::TestBinaryTreeNode#test_add_from_hash101,4024
|
132
|
+
def test_add::TestTree::TestBinaryTreeNode#test_add134,5134
|
133
|
+
def test_inordered_each::TestTree::TestBinaryTreeNode#test_inordered_each157,6048
|
134
|
+
def test_left_child::TestTree::TestBinaryTreeNode#test_left_child201,7516
|
135
|
+
def test_right_child::TestTree::TestBinaryTreeNode#test_right_child209,7829
|
136
|
+
def test_left_child_equals::TestTree::TestBinaryTreeNode#test_left_child_equals217,8142
|
137
|
+
def test_right_child_equals::TestTree::TestBinaryTreeNode#test_right_child_equals236,9132
|
138
|
+
def test_is_left_child_eh::TestTree::TestBinaryTreeNode#test_is_left_child_eh256,10249
|
139
|
+
def test_is_right_child_eh::TestTree::TestBinaryTreeNode#test_is_right_child_eh271,10788
|
140
|
+
def test_swap_children::TestTree::TestBinaryTreeNode#test_swap_children285,11334
|
141
|
+
def test_old_camelCase_method_names::TestTree::TestBinaryTreeNode#test_old_camelCase_method_names303,12217
|
142
|
+
|
143
|
+
test/test_rubytree_require.rb,203
|
144
|
+
module TestTree::TestTree38,1678
|
145
|
+
class TestRequireRubytree::TestTree::TestRequireRubytree41,1759
|
146
|
+
def test_create_a_simple_node::TestTree::TestRequireRubytree#test_create_a_simple_node44,1884
|
147
|
+
|
148
|
+
test/test_subclassed_node.rb,389
|
149
|
+
module TestTree::TestTree39,1688
|
150
|
+
class TestSubclassedTreeNode::TestTree::TestSubclassedTreeNode42,1741
|
151
|
+
class MyNode::TestTree::TestSubclassedTreeNode::MyNode45,1868
|
152
|
+
def my_dummy_method::TestTree::TestSubclassedTreeNode::MyNode#my_dummy_method47,1967
|
153
|
+
def test_subclassed_camelcase_methods::TestTree::TestSubclassedTreeNode#test_subclassed_camelcase_methods52,2026
|
154
|
+
|
155
|
+
test/test_thread_and_fiber.rb,422
|
156
|
+
module TestTree::TestTree39,1695
|
157
|
+
class TestFiberAndThreadOnNode::TestTree::TestFiberAndThreadOnNode41,1747
|
158
|
+
def create_long_depth_trees::TestTree::TestFiberAndThreadOnNode#create_long_depth_trees44,1843
|
159
|
+
def test_fiber_for_recursion::TestTree::TestFiberAndThreadOnNode#test_fiber_for_recursion59,2260
|
160
|
+
def test_thread_for_recursion::TestTree::TestFiberAndThreadOnNode#test_thread_for_recursion73,2807
|
161
|
+
|
162
|
+
test/test_tree.rb,6262
|
163
|
+
module TestTree::TestTree39,1725
|
164
|
+
class TestTreeNode::TestTree::TestTreeNode41,1777
|
165
|
+
def setup::TestTree::TestTreeNode#setup65,2610
|
166
|
+
def setup_test_tree::TestTree::TestTreeNode#setup_test_tree77,3030
|
167
|
+
def teardown::TestTree::TestTreeNode#teardown84,3180
|
168
|
+
def test_has_version_number::TestTree::TestTreeNode#test_has_version_number89,3272
|
169
|
+
def test_root_setup::TestTree::TestTreeNode#test_root_setup94,3423
|
170
|
+
def test_root::TestTree::TestTreeNode#test_root111,4473
|
171
|
+
def test_from_hash::TestTree::TestTreeNode#test_from_hash123,4974
|
172
|
+
def test_from_hash_with_nils::TestTree::TestTreeNode#test_from_hash_with_nils175,6546
|
173
|
+
def test_add_from_hash::TestTree::TestTreeNode#test_add_from_hash221,7902
|
174
|
+
def test_to_h::TestTree::TestTreeNode#test_to_h253,8917
|
175
|
+
def test_to_h_from_hash_symmetry::TestTree::TestTreeNode#test_to_h_from_hash_symmetry279,9496
|
176
|
+
def test_has_content_eh::TestTree::TestTreeNode#test_has_content_eh295,9894
|
177
|
+
def test_length_is_size::TestTree::TestTreeNode#test_length_is_size306,10352
|
178
|
+
def test_spaceship::TestTree::TestTreeNode#test_spaceship312,10542
|
179
|
+
def test_is_comparable::TestTree::TestTreeNode#test_is_comparable338,11325
|
180
|
+
def test_to_s::TestTree::TestTreeNode#test_to_s356,12107
|
181
|
+
def test_first_sibling::TestTree::TestTreeNode#test_first_sibling389,13825
|
182
|
+
def test_is_first_sibling_eh::TestTree::TestTreeNode#test_is_first_sibling_eh402,14553
|
183
|
+
def test_is_last_sibling_eh::TestTree::TestTreeNode#test_is_last_sibling_eh413,15036
|
184
|
+
def test_last_sibling::TestTree::TestTreeNode#test_last_sibling424,15504
|
185
|
+
def test_siblings::TestTree::TestTreeNode#test_siblings436,16158
|
186
|
+
def test_is_only_child_eh::TestTree::TestTreeNode#test_is_only_child_eh464,17081
|
187
|
+
def test_next_sibling::TestTree::TestTreeNode#test_next_sibling475,17517
|
188
|
+
def test_previous_sibling::TestTree::TestTreeNode#test_previous_sibling486,18017
|
189
|
+
def test_add::TestTree::TestTreeNode#test_add497,18546
|
190
|
+
def test_add_duplicate::TestTree::TestTreeNode#test_add_duplicate518,19228
|
191
|
+
def test_add_at_specific_position::TestTree::TestTreeNode#test_add_at_specific_position559,20656
|
192
|
+
def test_replace_bang::TestTree::TestTreeNode#test_replace_bang623,23711
|
193
|
+
def test_replace_with::TestTree::TestTreeNode#test_replace_with647,24756
|
194
|
+
def test_remove_bang::TestTree::TestTreeNode#test_remove_bang665,25481
|
195
|
+
def test_remove_all_bang::TestTree::TestTreeNode#test_remove_all_bang697,26444
|
196
|
+
def test_remove_from_parent_bang::TestTree::TestTreeNode#test_remove_from_parent_bang707,26750
|
197
|
+
def test_children::TestTree::TestTreeNode#test_children726,27465
|
198
|
+
def test_first_child::TestTree::TestTreeNode#test_first_child762,29054
|
199
|
+
def test_last_child::TestTree::TestTreeNode#test_last_child771,29382
|
200
|
+
def test_find::TestTree::TestTreeNode#test_find780,29698
|
201
|
+
def test_parentage::TestTree::TestTreeNode#test_parentage795,30293
|
202
|
+
def test_each::TestTree::TestTreeNode#test_each804,30625
|
203
|
+
def test_each_leaf::TestTree::TestTreeNode#test_each_leaf823,31309
|
204
|
+
def test_parent::TestTree::TestTreeNode#test_parent850,32504
|
205
|
+
def test_indexed_access::TestTree::TestTreeNode#test_indexed_access861,32923
|
206
|
+
def test_print_tree::TestTree::TestTreeNode#test_print_tree872,33296
|
207
|
+
def test_marshal_dump::TestTree::TestTreeNode#test_marshal_dump879,33456
|
208
|
+
alias test_marshal_load::TestTree::TestTreeNode#test_marshal_load921,35578
|
209
|
+
def test_collect::TestTree::TestTreeNode#test_collect924,35699
|
210
|
+
def test_freeze_tree_bang::TestTree::TestTreeNode#test_freeze_tree_bang934,35965
|
211
|
+
def test_content::TestTree::TestTreeNode#test_content948,36487
|
212
|
+
def test_depth::TestTree::TestTreeNode#test_depth956,36878
|
213
|
+
def do_deprecated_depth::TestTree::TestTreeNode#do_deprecated_depth967,37251
|
214
|
+
def test_node_height::TestTree::TestTreeNode#test_node_height985,37819
|
215
|
+
def test_node_depth::TestTree::TestTreeNode#test_node_depth1010,39028
|
216
|
+
def test_level::TestTree::TestTreeNode#test_level1023,39465
|
217
|
+
def test_breadth::TestTree::TestTreeNode#test_breadth1038,40008
|
218
|
+
def test_breadth_each::TestTree::TestTreeNode#test_breadth_each1057,40655
|
219
|
+
def test_preordered_each::TestTree::TestTreeNode#test_preordered_each1106,42240
|
220
|
+
def test_postordered_each::TestTree::TestTreeNode#test_postordered_each1145,43494
|
221
|
+
def test_detached_copy::TestTree::TestTreeNode#test_detached_copy1194,45031
|
222
|
+
def test_detached_subtree_copy::TestTree::TestTreeNode#test_detached_subtree_copy1211,45759
|
223
|
+
def test_has_children_eh::TestTree::TestTreeNode#test_has_children_eh1245,48011
|
224
|
+
def test_is_leaf_eh::TestTree::TestTreeNode#test_is_leaf_eh1251,48173
|
225
|
+
def test_is_root_eh::TestTree::TestTreeNode#test_is_root_eh1258,48379
|
226
|
+
def test_content_equals::TestTree::TestTreeNode#test_content_equals1264,48542
|
227
|
+
def test_size::TestTree::TestTreeNode#test_size1272,48807
|
228
|
+
def test_lt2::TestTree::TestTreeNode#test_lt21281,49071
|
229
|
+
def test_index::TestTree::TestTreeNode#test_index1292,49563
|
230
|
+
def test_in_degree::TestTree::TestTreeNode#test_in_degree1313,50659
|
231
|
+
def test_out_degree::TestTree::TestTreeNode#test_out_degree1324,51126
|
232
|
+
def test_json_serialization::TestTree::TestTreeNode#test_json_serialization1335,51613
|
233
|
+
def test_json_deserialization::TestTree::TestTreeNode#test_json_deserialization1359,52413
|
234
|
+
def test_json_roundtrip::TestTree::TestTreeNode#test_json_roundtrip1387,53599
|
235
|
+
def test_old_camelCase_method_names::TestTree::TestTreeNode#test_old_camelCase_method_names1403,54340
|
236
|
+
def test_integer_node_names::TestTree::TestTreeNode#test_integer_node_names1434,55408
|
237
|
+
def test_add_node_to_self_as_child::TestTree::TestTreeNode#test_add_node_to_self_as_child1465,56638
|
238
|
+
def test_single_node_becomes_leaf::TestTree::TestTreeNode#test_single_node_becomes_leaf1481,57151
|
239
|
+
def test_unique_node_names::TestTree::TestTreeNode#test_unique_node_names1493,57572
|
240
|
+
def setup_other_test_tree::TestTree::TestTreeNode#setup_other_test_tree1507,57927
|
241
|
+
def test_merge::TestTree::TestTreeNode#test_merge1535,58916
|
242
|
+
def test_merge_bang::TestTree::TestTreeNode#test_merge_bang1564,60354
|
data/TODO.org
CHANGED
@@ -186,8 +186,18 @@
|
|
186
186
|
|
187
187
|
|
188
188
|
|
189
|
+
* R0.9.5
|
190
|
+
** DONE Pull the =hash= converter code from [[https://github.com/markthomas/RubyTree/commits/master][Mark Thomas]] ([[Issue:13][Issue #13]]). :ARCHIVE:
|
191
|
+
CLOSED: [2014-11-01 Sat 20:10]
|
192
|
+
This was contributed by @jhamon.
|
193
|
+
** DONE Misc. bug fixes :ARCHIVE:
|
194
|
+
CLOSED: [2014-11-01 Sat 20:11]
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
|
189
199
|
* Next Release
|
190
|
-
DEADLINE: <2014-
|
200
|
+
DEADLINE: <2014-12-01 Mon>
|
191
201
|
** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial:
|
192
202
|
[[Issue:5][Issue #5.]]
|
193
203
|
|
@@ -219,19 +229,15 @@
|
|
219
229
|
duplicates). This needs to be a hash (to allow O(1) access),
|
220
230
|
and will sacrifice memory. There might be a need to
|
221
231
|
restructure the internals to make better use of memory.
|
232
|
+
** STARTED Convert all documentation to markdown mode.
|
222
233
|
** TODO Expand the examples section, and add supporting documentation
|
223
|
-
** TODO Pull the =hash= converter code from [[https://github.com/markthomas/RubyTree/commits/master][Mark Thomas]] ([[Issue:13][Issue #13]]).
|
224
|
-
** TODO Convert all documentation to markdown mode.
|
225
|
-
|
226
|
-
|
227
234
|
* Unplanned / Not assigned to any release
|
228
|
-
*** DONE [#A] Migrate the website and references from http://rubyforge.org/
|
235
|
+
*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
|
229
236
|
CLOSED: [2014-07-04 Fri 22:18]
|
230
|
-
***
|
231
|
-
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]]
|
237
|
+
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
|
232
238
|
CLOSED: [2014-01-12 Sun 19:06]
|
233
239
|
The issue seems to have been resolved with the 2.2.1 release of Rubygems.
|
234
|
-
|
240
|
+
*** TODO Create a cycle-detection/validation mechanism to prevent cyclic graphs of nodes.
|
235
241
|
*** TODO Create a generic validation method to check for various issues in the created tree.
|
236
242
|
*** TODO Add a FAQ document to the project.
|
237
243
|
*** TODO The semantic of length is probably unclear. Should return the node_depth instead (or remove the method)
|
data/lib/tree.rb
CHANGED
@@ -89,6 +89,7 @@ module Tree
|
|
89
89
|
include Tree::Utils::CamelCaseMethodHandler
|
90
90
|
include Tree::Utils::JSONConverter
|
91
91
|
include Tree::Utils::TreeMergeHandler
|
92
|
+
include Tree::Utils::HashConverter
|
92
93
|
|
93
94
|
# @!group Core Attributes
|
94
95
|
|
@@ -380,6 +381,31 @@ module Tree
|
|
380
381
|
|
381
382
|
private :insertion_range
|
382
383
|
|
384
|
+
|
385
|
+
# Replaces the specified child node with another child node on this node.
|
386
|
+
#
|
387
|
+
# @param [Tree::TreeNode] old_child The child node to be replaced.
|
388
|
+
# @param [Tree::TreeNode] new_child The child node to be replaced with.
|
389
|
+
#
|
390
|
+
# @return [Tree::TreeNode] The removed child node
|
391
|
+
def replace!(old_child, new_child)
|
392
|
+
child_index = @children.find_index(old_child)
|
393
|
+
|
394
|
+
old_child = remove! old_child
|
395
|
+
add new_child, child_index
|
396
|
+
|
397
|
+
return old_child
|
398
|
+
end
|
399
|
+
|
400
|
+
# Replaces the node with another node
|
401
|
+
#
|
402
|
+
# @param [Tree::TreeNode] node The node to replace this node with
|
403
|
+
#
|
404
|
+
# @return [Tree::TreeNode] The replaced child node
|
405
|
+
def replace_with(node)
|
406
|
+
@parent.replace!(self, node)
|
407
|
+
end
|
408
|
+
|
383
409
|
# Removes the specified child node from this node.
|
384
410
|
#
|
385
411
|
# This method can also be used for *pruning* a sub-tree, in cases where the removed child node is
|
@@ -560,7 +586,7 @@ module Tree
|
|
560
586
|
# @return [Tree::TreeNode] this node, if a block if given
|
561
587
|
# @return [Enumerator] an enumerator on this tree, if a block is *not* given
|
562
588
|
def postordered_each(&block)
|
563
|
-
return self.to_enum unless block_given?
|
589
|
+
return self.to_enum(:postordered_each) unless block_given?
|
564
590
|
|
565
591
|
# Using a marked node in order to skip adding the children of nodes that
|
566
592
|
# have already been visited. This allows the stack depth to be controlled,
|
@@ -596,7 +622,7 @@ module Tree
|
|
596
622
|
# @return [Tree::TreeNode] this node, if a block if given
|
597
623
|
# @return [Enumerator] an enumerator on this tree, if a block is *not* given
|
598
624
|
def breadth_each(&block)
|
599
|
-
return self.to_enum unless block_given?
|
625
|
+
return self.to_enum(:breadth_each) unless block_given?
|
600
626
|
|
601
627
|
node_queue = [self] # Create a queue with self as the initial entry
|
602
628
|
|
@@ -805,20 +831,26 @@ module Tree
|
|
805
831
|
# Pretty prints the (sub)tree rooted at this node.
|
806
832
|
#
|
807
833
|
# @param [Integer] level The indentation level (4 spaces) to start with.
|
808
|
-
|
834
|
+
# @param [Integer] max_depth optional maximum depth at which the printing with stop.
|
835
|
+
# @param [Proc] block optional block to use for rendering
|
836
|
+
def print_tree(level = 0, max_depth = nil, block = lambda { |node, prefix| puts "#{prefix} #{node.name}" })
|
837
|
+
prefix = ''
|
838
|
+
|
809
839
|
if is_root?
|
810
|
-
|
840
|
+
prefix << '*'
|
811
841
|
else
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
842
|
+
prefix << '|' unless parent.is_last_sibling?
|
843
|
+
prefix << (' ' * (level - 1) * 4)
|
844
|
+
prefix << (is_last_sibling? ? '+' : '|')
|
845
|
+
prefix << '---'
|
846
|
+
prefix << (has_children? ? '+' : '>')
|
817
847
|
end
|
818
848
|
|
819
|
-
|
849
|
+
block.call(self, prefix)
|
850
|
+
|
851
|
+
return unless max_depth.nil? || level < max_depth # Exit if the max level is defined, and reached.
|
820
852
|
|
821
|
-
children { |child| child.print_tree(level + 1) if child } # Child might be 'nil'
|
853
|
+
children { |child| child.print_tree(level + 1, max_depth, block) if child } # Child might be 'nil'
|
822
854
|
end
|
823
855
|
|
824
856
|
end
|
data/lib/tree/binarytree.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
9
9
|
#
|
10
10
|
|
11
|
-
# Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013 Anupam Sengupta
|
11
|
+
# Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013, 2014 Anupam Sengupta
|
12
12
|
#
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -113,6 +113,38 @@ module Tree
|
|
113
113
|
super(child)
|
114
114
|
end
|
115
115
|
|
116
|
+
|
117
|
+
# Instantiate and insert child nodes from data in a Ruby +Hash+
|
118
|
+
#
|
119
|
+
# This method is used in conjunction with {Tree::TreeNode.from_hash} to
|
120
|
+
# provide a convenient way of building and inserting child nodes present
|
121
|
+
# in a Ruby hashes.
|
122
|
+
#
|
123
|
+
# This method will instantiate a {Tree::TreeNode} instance for each top-
|
124
|
+
# level key of the input hash, to be inserted as children of the receiver
|
125
|
+
# instance.
|
126
|
+
#
|
127
|
+
# Nested hashes are expected and further child nodes will be created and
|
128
|
+
# added accordingly. If a hash key is a single value that value will be
|
129
|
+
# used as the name for the node. If a hash key is an Array, both node
|
130
|
+
# name and content will be populated.
|
131
|
+
#
|
132
|
+
# A leaf element of the tree should be represented as a hash key with
|
133
|
+
# corresponding value nil or {}.
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# root = Tree::TreeNode.new(:A, "Root content!")
|
137
|
+
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
138
|
+
#
|
139
|
+
# @param [Hash] hashed_subtree The hash of child subtrees.
|
140
|
+
# @raise [ArgumentError] This exception is raised if hash contains too many children.
|
141
|
+
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
142
|
+
# @return [Array] Array of child nodes added
|
143
|
+
def add_from_hash(hashed_subtree)
|
144
|
+
raise ArgumentError, "Too many children" if hashed_subtree.size + @children.size > 2
|
145
|
+
super(hashed_subtree)
|
146
|
+
end
|
147
|
+
|
116
148
|
# Performs inorder traversal (including this node).
|
117
149
|
#
|
118
150
|
# @yieldparam node [Tree::BinaryTreeNode] Each node (in-order).
|
data/lib/tree/tree_deps.rb
CHANGED
@@ -0,0 +1,161 @@
|
|
1
|
+
# hash_converter.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
# = hash_converter.rb - Provides utility methods for converting between
|
4
|
+
# {Tree::TreeNode} and Ruby's native +Hash+.
|
5
|
+
#
|
6
|
+
# Author:: Jen Hamon (http://www.github.com/jhamon)
|
7
|
+
#
|
8
|
+
# Time-stamp: <2014-10-25 16:20:23 anupam>
|
9
|
+
#
|
10
|
+
# Copyright (C) 2014 Jen Hamon (http://www.github.com/jhamon) and
|
11
|
+
# Anupam Sengupta <anupamsg@gmail.com>
|
12
|
+
#
|
13
|
+
# All rights reserved.
|
14
|
+
#
|
15
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
16
|
+
# are permitted provided that the following conditions are met:
|
17
|
+
#
|
18
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
19
|
+
# list of conditions and the following disclaimer.
|
20
|
+
#
|
21
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
22
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
23
|
+
# other materials provided with the distribution.
|
24
|
+
#
|
25
|
+
# - Neither the name of the organization nor the names of its contributors may
|
26
|
+
# be used to endorse or promote products derived from this software without
|
27
|
+
# specific prior written permission.
|
28
|
+
#
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
30
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
31
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
32
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
33
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
34
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
35
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
36
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
37
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
38
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
|
40
|
+
module Tree::Utils::HashConverter
|
41
|
+
|
42
|
+
def self.included(base)
|
43
|
+
base.extend(ClassMethods)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Methods in {Tree::Utils::HashConverter::ClassMethods} will be added as
|
47
|
+
# class methods on any class mixing in the {Tree::Utils::HashConverter}
|
48
|
+
# module.
|
49
|
+
module ClassMethods
|
50
|
+
|
51
|
+
# Factory method builds a {Tree::TreeNode} from a +Hash+.
|
52
|
+
#
|
53
|
+
# This method will interpret each key of your +Hash+ as a {Tree::TreeNode}.
|
54
|
+
# Nested hashes are expected and child nodes will be added accordingly. If
|
55
|
+
# a hash key is a single value that value will be used as the name for the
|
56
|
+
# node. If a hash key is an Array, both node name and content will be
|
57
|
+
# populated.
|
58
|
+
#
|
59
|
+
# A leaf element of the tree should be represented as a hash key with
|
60
|
+
# corresponding value +nil+ or +{}+.
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# TreeNode.from_hash({:A => {:B => {}, :C => {:D => {}, :E => {}}}})
|
64
|
+
# # would be parsed into the following tree structure:
|
65
|
+
# # A
|
66
|
+
# # / \
|
67
|
+
# # B C
|
68
|
+
# # / \
|
69
|
+
# # D E
|
70
|
+
#
|
71
|
+
# # The same tree would result from this nil-terminated Hash
|
72
|
+
# {:A => {:B => nil, :C => {:D => nil, :E => nil}}}
|
73
|
+
#
|
74
|
+
# # A tree with equivalent structure but with content present for
|
75
|
+
# # nodes A and D could be built from a hash like this:
|
76
|
+
# {[:A, "A content"] => {:B => {}, :C => {[:D, "D content"] => {}, :E => {}}}}
|
77
|
+
#
|
78
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
79
|
+
# @param [Hash] hash Hash to build tree from.
|
80
|
+
# @return [Tree::TreeNode] The {Tree::TreeNode} instance representing the root of your tree.
|
81
|
+
#
|
82
|
+
# @raise [ArgumentError] This exception is raised if a non-Hash is passed.
|
83
|
+
# @raise [ArgumentError] This exception is raised if the hash has multiple top-level elements.
|
84
|
+
# @raise [ArgumentError] This exception is raised if the hash contains values that are not hashes or nils.
|
85
|
+
|
86
|
+
def from_hash(hash)
|
87
|
+
raise ArgumentError, "Argument must be a type of hash" unless hash.is_a?(Hash)
|
88
|
+
raise ArgumentError, "Hash must have one top-level element" if hash.size != 1
|
89
|
+
|
90
|
+
root, children = hash.first
|
91
|
+
|
92
|
+
unless [Hash, NilClass].include?(children.class)
|
93
|
+
raise ArgumentError, "Invalid child. Must be nil or hash."
|
94
|
+
end
|
95
|
+
|
96
|
+
node = self.new(*root)
|
97
|
+
node.add_from_hash(children) unless children.nil?
|
98
|
+
node
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Instantiate and insert child nodes from data in a Ruby +Hash+
|
103
|
+
#
|
104
|
+
# This method is used in conjunction with from_hash to provide a
|
105
|
+
# convenient way of building and inserting child nodes present in a Ruby
|
106
|
+
# hashes.
|
107
|
+
#
|
108
|
+
# This method will instantiate a node instance for each top-
|
109
|
+
# level key of the input hash, to be inserted as children of the receiver
|
110
|
+
# instance.
|
111
|
+
#
|
112
|
+
# Nested hashes are expected and further child nodes will be created and
|
113
|
+
# added accordingly. If a hash key is a single value that value will be
|
114
|
+
# used as the name for the node. If a hash key is an Array, both node
|
115
|
+
# name and content will be populated.
|
116
|
+
#
|
117
|
+
# A leaf element of the tree should be represented as a hash key with
|
118
|
+
# corresponding value +nil+ or {}.
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# root = Tree::TreeNode.new(:A, "Root content!")
|
122
|
+
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
123
|
+
#
|
124
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
125
|
+
# @param [Hash] children The hash of child subtrees.
|
126
|
+
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
127
|
+
# @return [Array] Array of child nodes added
|
128
|
+
# @see ClassMethods#from_hash
|
129
|
+
def add_from_hash(children)
|
130
|
+
raise ArgumentError, "Argument must be a type of hash" unless children.is_a?(Hash)
|
131
|
+
|
132
|
+
child_nodes = []
|
133
|
+
children.each do |child, grandchildren|
|
134
|
+
child_node = self.class.from_hash({child => grandchildren})
|
135
|
+
child_nodes << child_node
|
136
|
+
self << child_node
|
137
|
+
end
|
138
|
+
|
139
|
+
child_nodes
|
140
|
+
end
|
141
|
+
|
142
|
+
# Convert a node and its subtree into a Ruby hash.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# root = Tree::TreeNode.new(:root, "root content")
|
146
|
+
# root << Tree::TreeNode.new(:child1, "child1 content")
|
147
|
+
# root << Tree::TreeNode.new(:child2, "child2 content")
|
148
|
+
# root.to_h # => {[:root, "root content"] => { [:child1, "child1 content"] => {}, [:child2, "child2 content"] => {}}}
|
149
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
150
|
+
# @return [Hash] Hash representation of tree.
|
151
|
+
def to_h
|
152
|
+
key = has_content? ? [name, content] : name
|
153
|
+
|
154
|
+
children_hash = {}
|
155
|
+
children do |child|
|
156
|
+
children_hash.merge! child.to_h
|
157
|
+
end
|
158
|
+
|
159
|
+
{ key => children_hash }
|
160
|
+
end
|
161
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# json_converter.rb - This file is part of the RubyTree package.
|
2
2
|
#
|
3
|
-
# =
|
3
|
+
# = json_converter.rb - Provides conversion to and from JSON.
|
4
4
|
#
|
5
5
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
6
6
|
#
|
7
|
-
# Time-stamp: <
|
7
|
+
# Time-stamp: <2014-10-25 16:16:23 anupam>
|
8
8
|
#
|
9
|
-
# Copyright (C) 2012, 2013 Anupam Sengupta <anupamsg@gmail.com>
|
9
|
+
# Copyright (C) 2012, 2013, 2014 Anupam Sengupta <anupamsg@gmail.com>
|
10
10
|
#
|
11
11
|
# All rights reserved.
|
12
12
|
#
|
data/lib/tree/version.rb
CHANGED
data/test/test_binarytree.rb
CHANGED
@@ -63,6 +63,73 @@ module TestTree
|
|
63
63
|
assert_equal(@root.children.size, 0, "Initially no children should be present")
|
64
64
|
end
|
65
65
|
|
66
|
+
def test_from_hash
|
67
|
+
# Can make a root note without a name
|
68
|
+
assert_raise (ArgumentError) { Tree::BinaryTreeNode.from_hash({})}
|
69
|
+
# Can't have multiple roots
|
70
|
+
assert_raise (ArgumentError) { Tree::BinaryTreeNode.from_hash({:A => {}, :B => {}}) }
|
71
|
+
|
72
|
+
# Can't have more than 2 children
|
73
|
+
too_many_kids = {:A => {:B => {}, :C => {}, :D => {} } }
|
74
|
+
assert_raise(ArgumentError) { Tree::BinaryTreeNode.from_hash(too_many_kids) }
|
75
|
+
|
76
|
+
valid_hash = {:A => {:B => {}, :C => { :D => {} } } }
|
77
|
+
tree = Tree::BinaryTreeNode.from_hash(valid_hash)
|
78
|
+
# A
|
79
|
+
# / \
|
80
|
+
# B C
|
81
|
+
# |
|
82
|
+
# D
|
83
|
+
|
84
|
+
assert_same(tree.class, Tree::BinaryTreeNode)
|
85
|
+
assert_same(tree.name, :A)
|
86
|
+
assert_equal(tree.is_root?, true)
|
87
|
+
assert_equal(tree.is_leaf?, false)
|
88
|
+
assert_equal(tree.children.count, 2) # B, C, D
|
89
|
+
assert_equal(tree.size, 4)
|
90
|
+
assert_equal(tree.left_child.name, :B)
|
91
|
+
assert_equal(tree.right_child.name, :C)
|
92
|
+
|
93
|
+
valid_hash_with_content = {[:A, "Content!"] => {:B => {}, :C => { [:D, "More content"] => {} } } }
|
94
|
+
tree2 = Tree::BinaryTreeNode.from_hash(valid_hash_with_content)
|
95
|
+
|
96
|
+
assert_equal(tree2.class, Tree::BinaryTreeNode)
|
97
|
+
assert_equal(tree2.content, "Content!" )
|
98
|
+
assert_equal(tree2[:C][:D].content, "More content")
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_add_from_hash
|
102
|
+
root = Tree::BinaryTreeNode.new("Root")
|
103
|
+
|
104
|
+
# Can't have too many children
|
105
|
+
too_many_kids = {:child1 => {}, :child2 => {}, :child3 => {}}
|
106
|
+
assert_raise(ArgumentError) { root.add_from_hash(too_many_kids) }
|
107
|
+
assert_equal(root.children.count, 0) # Nothing added
|
108
|
+
|
109
|
+
# Well behaved when adding nothing
|
110
|
+
assert_equal(root.add_from_hash({}), [])
|
111
|
+
assert_equal(root.size, 1)
|
112
|
+
|
113
|
+
valid_hash = {:A => {}, :B => { :C => {}, [:D, "leaf"] => {} } }
|
114
|
+
added = root.add_from_hash(valid_hash)
|
115
|
+
# root
|
116
|
+
# / \
|
117
|
+
# A B
|
118
|
+
# / \
|
119
|
+
# C D
|
120
|
+
|
121
|
+
assert_equal(added.class, Array)
|
122
|
+
assert_equal(added.count, 2)
|
123
|
+
assert_equal(root.size, 5)
|
124
|
+
assert_equal(root.children.count, 2)
|
125
|
+
assert_equal(root[:B][:D].content, "leaf")
|
126
|
+
|
127
|
+
# Can't add more than two children
|
128
|
+
assert_raise(ArgumentError) { root.add_from_hash({:X => {}}) }
|
129
|
+
node = Tree::BinaryTreeNode.new("Root 2")
|
130
|
+
assert_raise(ArgumentError) { node.add_from_hash({:A => {}, :B => {}, :C => {}}) }
|
131
|
+
end
|
132
|
+
|
66
133
|
# Test the add method.
|
67
134
|
def test_add
|
68
135
|
@root.add @left_child1
|
data/test/test_tree.rb
CHANGED
@@ -120,6 +120,177 @@ module TestTree
|
|
120
120
|
assert_equal(2 , @root.node_height, "Root's height after adding the children should be 2")
|
121
121
|
end
|
122
122
|
|
123
|
+
def test_from_hash
|
124
|
+
# A
|
125
|
+
# / | \
|
126
|
+
# B C D
|
127
|
+
# / \ /
|
128
|
+
# E F G
|
129
|
+
# / \
|
130
|
+
# H I
|
131
|
+
|
132
|
+
hash = {[:A, "Root content"] => {
|
133
|
+
:B => {
|
134
|
+
:E => {},
|
135
|
+
:F => {
|
136
|
+
:H => {},
|
137
|
+
[:I, "Leaf content"] => {}
|
138
|
+
}
|
139
|
+
},
|
140
|
+
:C => {},
|
141
|
+
:D => {
|
142
|
+
:G => {}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
tree = Tree::TreeNode.from_hash(hash)
|
148
|
+
|
149
|
+
assert_same(tree.class, Tree::TreeNode)
|
150
|
+
assert_same(tree.name, :A)
|
151
|
+
assert_equal(tree.is_root?, true)
|
152
|
+
assert_equal(tree.is_leaf?, false)
|
153
|
+
assert_equal(tree.size, 9)
|
154
|
+
assert_equal(tree.content, "Root content")
|
155
|
+
assert_equal(tree.children.count, 3) # B, C, D
|
156
|
+
|
157
|
+
leaf_with_content = tree[:B][:F][:I]
|
158
|
+
assert_equal(leaf_with_content.content, "Leaf content")
|
159
|
+
assert_equal(leaf_with_content.is_leaf?, true)
|
160
|
+
|
161
|
+
leaf_without_content = tree[:C]
|
162
|
+
assert_equal(leaf_without_content.is_leaf?, true)
|
163
|
+
|
164
|
+
interior_node = tree[:B][:F]
|
165
|
+
assert_equal(interior_node.is_leaf?, false)
|
166
|
+
assert_equal(interior_node.children.count, 2)
|
167
|
+
|
168
|
+
# Can't make a node without a name
|
169
|
+
assert_raise (ArgumentError) { Tree::TreeNode.from_hash({}) }
|
170
|
+
# Can't have multiple roots
|
171
|
+
assert_raise (ArgumentError) { Tree::TreeNode.from_hash({:A => {}, :B => {}}) }
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_from_hash_with_nils
|
176
|
+
# A
|
177
|
+
# / | \
|
178
|
+
# B C D
|
179
|
+
# / \ /
|
180
|
+
# E F G
|
181
|
+
# / \
|
182
|
+
# H I
|
183
|
+
|
184
|
+
hash = {[:A, "Root content"] => {
|
185
|
+
:B => {
|
186
|
+
:E => nil,
|
187
|
+
:F => {
|
188
|
+
:H => nil,
|
189
|
+
[:I, "Leaf content"] => nil
|
190
|
+
}
|
191
|
+
},
|
192
|
+
:C => nil,
|
193
|
+
:D => {
|
194
|
+
:G => nil
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
tree = Tree::TreeNode.from_hash(hash)
|
200
|
+
|
201
|
+
assert_same(tree.class, Tree::TreeNode)
|
202
|
+
assert_same(tree.name, :A)
|
203
|
+
assert_equal(tree.is_root?, true)
|
204
|
+
assert_equal(tree.is_leaf?, false)
|
205
|
+
assert_equal(tree.size, 9)
|
206
|
+
assert_equal(tree.content, "Root content")
|
207
|
+
assert_equal(tree.children.count, 3) # B, C, D
|
208
|
+
|
209
|
+
leaf_with_content = tree[:B][:F][:I]
|
210
|
+
assert_equal(leaf_with_content.content, "Leaf content")
|
211
|
+
assert_equal(leaf_with_content.is_leaf?, true)
|
212
|
+
|
213
|
+
leaf_without_content = tree[:C]
|
214
|
+
assert_equal(leaf_without_content.is_leaf?, true)
|
215
|
+
|
216
|
+
interior_node = tree[:B][:F]
|
217
|
+
assert_equal(interior_node.is_leaf?, false)
|
218
|
+
assert_equal(interior_node.children.count, 2)
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_add_from_hash
|
222
|
+
tree = Tree::TreeNode.new(:A)
|
223
|
+
|
224
|
+
# Doesn't blow up when added an empty hash
|
225
|
+
hash = {}
|
226
|
+
assert_equal(tree.add_from_hash(hash), [])
|
227
|
+
|
228
|
+
# Okay, now try a real hash
|
229
|
+
hash = {:B => {:C => {:D => nil}, :E => {}, :F => {}}, [:G, "G content"] => {}}
|
230
|
+
# A
|
231
|
+
# / \
|
232
|
+
# B G
|
233
|
+
# /|\
|
234
|
+
# C E F
|
235
|
+
# |
|
236
|
+
# D
|
237
|
+
|
238
|
+
added_children = tree.add_from_hash(hash)
|
239
|
+
assert_equal(added_children.class, Array)
|
240
|
+
assert_equal(added_children.count, 2)
|
241
|
+
assert_equal(tree.size, 7)
|
242
|
+
assert_equal(tree[:G].content, "G content")
|
243
|
+
assert_equal(tree[:G].is_leaf?, true)
|
244
|
+
assert_equal(tree[:B].size, 5)
|
245
|
+
assert_equal(tree[:B].children.count, 3)
|
246
|
+
|
247
|
+
assert_raise (ArgumentError) { tree.add_from_hash([]) }
|
248
|
+
assert_raise (ArgumentError) { tree.add_from_hash("not a hash") }
|
249
|
+
assert_raise (ArgumentError) { tree.add_from_hash({:X => "Not a hash or nil"}) }
|
250
|
+
end
|
251
|
+
|
252
|
+
# Test exporting to ruby Hash
|
253
|
+
def test_to_h
|
254
|
+
a = Tree::TreeNode.new(:A)
|
255
|
+
b = Tree::TreeNode.new(:B)
|
256
|
+
c = Tree::TreeNode.new(:C)
|
257
|
+
d = Tree::TreeNode.new(:D)
|
258
|
+
e = Tree::TreeNode.new(:E)
|
259
|
+
f = Tree::TreeNode.new(:F)
|
260
|
+
g = Tree::TreeNode.new(:G)
|
261
|
+
# A
|
262
|
+
# / \
|
263
|
+
# B C
|
264
|
+
# | / \
|
265
|
+
# E F G
|
266
|
+
|
267
|
+
a << b
|
268
|
+
a << c
|
269
|
+
c << f
|
270
|
+
c << g
|
271
|
+
b << e
|
272
|
+
|
273
|
+
exported = a.to_h
|
274
|
+
expected = {:A => {:B => {:E => {}}, :C => {:F => {}, :G => {}}}}
|
275
|
+
assert_equal(exported, expected)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Test that from_hash and to_h are symmetric
|
279
|
+
def test_to_h_from_hash_symmetry
|
280
|
+
# A
|
281
|
+
# / \
|
282
|
+
# B C
|
283
|
+
# /|\ \
|
284
|
+
# E F G H
|
285
|
+
# |\ |
|
286
|
+
# I J K
|
287
|
+
|
288
|
+
input = {:A => {:B => {:E => {:I => {}, :J =>{}}, :F => {}, :G => {}}, :C =>{:H => {:K => {}}}}}
|
289
|
+
|
290
|
+
node = Tree::TreeNode.from_hash(input)
|
291
|
+
assert_equal(node.to_h, input)
|
292
|
+
end
|
293
|
+
|
123
294
|
# Test the presence of content in the nodes.
|
124
295
|
def test_has_content_eh
|
125
296
|
a_node = Tree::TreeNode.new("A Node")
|
@@ -448,6 +619,48 @@ module TestTree
|
|
448
619
|
assert_equal(5, @root.children.size, "Should have five child nodes")
|
449
620
|
end
|
450
621
|
|
622
|
+
# Test the replace! and replace_with! methods
|
623
|
+
def test_replace_bang
|
624
|
+
@root << @child1
|
625
|
+
@root << @child2
|
626
|
+
@root << @child3
|
627
|
+
|
628
|
+
assert_equal(4, @root.size, "Should have four nodes")
|
629
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
630
|
+
assert(@root.children.include?(@child2), "Should parent child2")
|
631
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
632
|
+
assert(!@root.children.include?(@child4), "Should not parent child4")
|
633
|
+
|
634
|
+
@root.replace!(@child2, @child4)
|
635
|
+
|
636
|
+
# Also test replacing with a node of the same name
|
637
|
+
@root.replace! @child4, @child4.detached_copy
|
638
|
+
|
639
|
+
assert_equal(4, @root.size, "Should have three nodes")
|
640
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
641
|
+
assert(!@root.children.include?(@child2), "Should not parent child2")
|
642
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
643
|
+
assert(@root.children.include?(@child4), "Should parent child4")
|
644
|
+
assert_equal(1, @root.children.find_index(@child4), "Should add child4 to index 1")
|
645
|
+
end
|
646
|
+
|
647
|
+
def test_replace_with
|
648
|
+
@root << @child1
|
649
|
+
@root << @child2
|
650
|
+
|
651
|
+
assert_equal(3, @root.size, "Should have three nodes")
|
652
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
653
|
+
assert(@root.children.include?(@child2), "Should parent child2")
|
654
|
+
assert(!@root.children.include?(@child3), "Should not parent child3")
|
655
|
+
|
656
|
+
@child2.replace_with @child3
|
657
|
+
|
658
|
+
assert_equal(3, @root.size, "Should have three nodes")
|
659
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
660
|
+
assert(!@root.children.include?(@child2), "Should not parent child2")
|
661
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
662
|
+
end
|
663
|
+
|
451
664
|
# Test the remove! and remove_all! methods.
|
452
665
|
def test_remove_bang
|
453
666
|
@root << @child1
|
@@ -868,17 +1081,25 @@ module TestTree
|
|
868
1081
|
f << h
|
869
1082
|
j << k << z
|
870
1083
|
|
871
|
-
#
|
872
|
-
result_array =
|
1084
|
+
# Test when a block is given
|
1085
|
+
result_array = []
|
873
1086
|
result = j.breadth_each { |node| result_array << node.detached_copy }
|
874
1087
|
|
875
|
-
assert_equal(j, result)
|
1088
|
+
assert_equal(j, result) # The invocation target is returned
|
1089
|
+
|
1090
|
+
expected_array.each_index do |i|
|
1091
|
+
assert_equal(expected_array[i].name, result_array[i].name) # Match only the names.
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
assert_equal(Enumerator, j.breadth_each.class) if defined?(Enumerator.class ) # Without a block
|
1095
|
+
assert_equal(Enumerable::Enumerator, j.breadth_each.class) if defined?(Enumerable::Enumerator.class) # Without a block
|
1096
|
+
|
1097
|
+
# Now test without a block
|
1098
|
+
result_array = j.breadth_each.collect { |node| node}
|
876
1099
|
expected_array.each_index do |i|
|
877
1100
|
assert_equal(expected_array[i].name, result_array[i].name) # Match only the names.
|
878
1101
|
end
|
879
1102
|
|
880
|
-
assert_equal(Enumerator, j.breadth_each.class) if defined?(Enumerator.class )# Without a block
|
881
|
-
assert_equal(Enumerable::Enumerator, j.breadth_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
|
882
1103
|
end
|
883
1104
|
|
884
1105
|
# Test the preordered_each method.
|
@@ -945,18 +1166,28 @@ module TestTree
|
|
945
1166
|
f << h
|
946
1167
|
j << k << z
|
947
1168
|
|
1169
|
+
# Test when a block is given
|
948
1170
|
result_array = []
|
949
1171
|
result = j.postordered_each { |node| result_array << node.detached_copy}
|
950
1172
|
|
951
|
-
assert_equal(j, result) #
|
1173
|
+
assert_equal(j, result) # The invocation target is returned
|
1174
|
+
|
1175
|
+
expected_array.each_index do |i|
|
1176
|
+
# Match only the names.
|
1177
|
+
assert_equal(expected_array[i].name, result_array[i].name)
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
assert_equal(Enumerator, j.postordered_each.class) if defined?(Enumerator.class) # Without a block
|
1181
|
+
assert_equal(Enumerable::Enumerator, j.postordered_each.class) if defined?(Enumerable::Enumerator.class) # Without a block
|
1182
|
+
|
1183
|
+
# Now test without a block
|
1184
|
+
result_array = j.postordered_each.collect { |node| node }
|
952
1185
|
|
953
1186
|
expected_array.each_index do |i|
|
954
1187
|
# Match only the names.
|
955
1188
|
assert_equal(expected_array[i].name, result_array[i].name)
|
956
1189
|
end
|
957
1190
|
|
958
|
-
assert_equal(Enumerator, j.postordered_each.class) if defined?(Enumerator.class )# Without a block
|
959
|
-
assert_equal(Enumerable::Enumerator, j.postordered_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
|
960
1191
|
end
|
961
1192
|
|
962
1193
|
# test the detached_copy method.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubytree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anupam Sengupta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01
|
11
|
+
date: 2014-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: structured_warnings
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- LICENSE.md
|
137
137
|
- README.md
|
138
138
|
- Rakefile
|
139
|
+
- TAGS
|
139
140
|
- TODO.org
|
140
141
|
- examples/example_basic.rb
|
141
142
|
- lib/rubytree.rb
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- lib/tree/binarytree.rb
|
144
145
|
- lib/tree/tree_deps.rb
|
145
146
|
- lib/tree/utils/camel_case_method_handler.rb
|
147
|
+
- lib/tree/utils/hash_converter.rb
|
146
148
|
- lib/tree/utils/json_converter.rb
|
147
149
|
- lib/tree/utils/metrics_methods.rb
|
148
150
|
- lib/tree/utils/tree_merge_handler.rb
|
@@ -179,12 +181,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
181
|
version: 1.8.7
|
180
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
183
|
requirements:
|
182
|
-
- - "
|
184
|
+
- - ">"
|
183
185
|
- !ruby/object:Gem::Version
|
184
|
-
version:
|
186
|
+
version: 1.3.1
|
185
187
|
requirements: []
|
186
188
|
rubyforge_project:
|
187
|
-
rubygems_version: 2.2.
|
189
|
+
rubygems_version: 2.2.2
|
188
190
|
signing_key:
|
189
191
|
specification_version: 4
|
190
192
|
summary: A generic tree data structure.
|