radix_tree 1.0.0.dev.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/radix_tree.rb +81 -10
- data/test/helper.rb +5 -2
- data/test/test_radix_tree.rb +53 -0
- metadata +11 -5
data/lib/radix_tree.rb
CHANGED
@@ -4,6 +4,20 @@
|
|
4
4
|
# 25 times slower for 10 bytes key, 100000 elements insertion
|
5
5
|
# 10 times slower for 10 bytes key, 100000 elements retrieval
|
6
6
|
#
|
7
|
+
# TODO: Implement following methods for Hash compatibility.
|
8
|
+
# * delete_if
|
9
|
+
# * reject
|
10
|
+
# * reject!
|
11
|
+
# * fetch
|
12
|
+
# * values_at
|
13
|
+
# * replace
|
14
|
+
# * key
|
15
|
+
# * shift
|
16
|
+
# * has_value?/value?
|
17
|
+
# * ==
|
18
|
+
# * eql?
|
19
|
+
# * hash
|
20
|
+
#
|
7
21
|
# TODO: Implement following features for utilizing strength of Radix Tree.
|
8
22
|
# * find predecessor
|
9
23
|
# * find successor
|
@@ -28,7 +42,7 @@ class RadixTree
|
|
28
42
|
end
|
29
43
|
|
30
44
|
def empty?
|
31
|
-
|
45
|
+
!@children and undefined?
|
32
46
|
end
|
33
47
|
|
34
48
|
def size
|
@@ -101,14 +115,7 @@ class RadixTree
|
|
101
115
|
if child = find_child(key)
|
102
116
|
value = child.delete(key)
|
103
117
|
if value and child.undefined?
|
104
|
-
|
105
|
-
delete_child(child)
|
106
|
-
elsif child.children.size == 1
|
107
|
-
# pull up the grand child as a child
|
108
|
-
delete_child(child)
|
109
|
-
grand = child.children.values.first
|
110
|
-
add_child(Node.new(child.key + grand.key, grand.value, grand.children))
|
111
|
-
end
|
118
|
+
reap(child)
|
112
119
|
end
|
113
120
|
value
|
114
121
|
end
|
@@ -156,6 +163,17 @@ class RadixTree
|
|
156
163
|
add_child(child)
|
157
164
|
end
|
158
165
|
|
166
|
+
def reap(child)
|
167
|
+
if !child.children
|
168
|
+
delete_child(child)
|
169
|
+
elsif child.children.size == 1
|
170
|
+
# pull up the grand child as a child
|
171
|
+
delete_child(child)
|
172
|
+
grand = child.children.values.first
|
173
|
+
add_child(Node.new(child.key + grand.key, grand.value, grand.children))
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
159
177
|
def child_key(key)
|
160
178
|
key[head_match_length(key)..-1]
|
161
179
|
end
|
@@ -190,6 +208,9 @@ class RadixTree
|
|
190
208
|
end
|
191
209
|
|
192
210
|
DEFAULT = Object.new
|
211
|
+
|
212
|
+
attr_accessor :default
|
213
|
+
attr_reader :default_proc
|
193
214
|
|
194
215
|
def initialize(default = DEFAULT, &block)
|
195
216
|
if block && default != DEFAULT
|
@@ -207,9 +228,50 @@ class RadixTree
|
|
207
228
|
def size
|
208
229
|
@root.size
|
209
230
|
end
|
231
|
+
alias length size
|
210
232
|
|
211
233
|
def each(&block)
|
212
|
-
|
234
|
+
if block_given?
|
235
|
+
@root.each('', &block)
|
236
|
+
self
|
237
|
+
else
|
238
|
+
Enumerator.new { |yielder|
|
239
|
+
@root.each('') do |k, v|
|
240
|
+
yielder << [k, v]
|
241
|
+
end
|
242
|
+
}
|
243
|
+
end
|
244
|
+
end
|
245
|
+
alias each_pair each
|
246
|
+
|
247
|
+
def each_key
|
248
|
+
if block_given?
|
249
|
+
@root.each('') do |k, v|
|
250
|
+
yield k
|
251
|
+
end
|
252
|
+
self
|
253
|
+
else
|
254
|
+
Enumerator.new { |yielder|
|
255
|
+
@root.each('') do |k, v|
|
256
|
+
yielder << k
|
257
|
+
end
|
258
|
+
}
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def each_value
|
263
|
+
if block_given?
|
264
|
+
@root.each('') do |k, v|
|
265
|
+
yield v
|
266
|
+
end
|
267
|
+
self
|
268
|
+
else
|
269
|
+
Enumerator.new { |yielder|
|
270
|
+
@root.each('') do |k, v|
|
271
|
+
yielder << v
|
272
|
+
end
|
273
|
+
}
|
274
|
+
end
|
213
275
|
end
|
214
276
|
|
215
277
|
def keys
|
@@ -220,9 +282,14 @@ class RadixTree
|
|
220
282
|
@root.values('')
|
221
283
|
end
|
222
284
|
|
285
|
+
def clear
|
286
|
+
@root = Node.new('')
|
287
|
+
end
|
288
|
+
|
223
289
|
def []=(key, value)
|
224
290
|
@root.store(key.to_s, value)
|
225
291
|
end
|
292
|
+
alias store []=
|
226
293
|
|
227
294
|
def key?(key)
|
228
295
|
@root.retrieve(key.to_s) != Node::UNDEFINED
|
@@ -252,4 +319,8 @@ class RadixTree
|
|
252
319
|
@root.dump_tree(io)
|
253
320
|
io
|
254
321
|
end
|
322
|
+
|
323
|
+
def to_hash
|
324
|
+
inject({}) { |r, (k, v)| r[k] = v; r }
|
325
|
+
end
|
255
326
|
end
|
data/test/helper.rb
CHANGED
data/test/test_radix_tree.rb
CHANGED
@@ -181,6 +181,8 @@ class TestRadixTree < Test::Unit::TestCase
|
|
181
181
|
s.each do |k, v|
|
182
182
|
h[k] = v
|
183
183
|
end
|
184
|
+
assert_equal s.to_a.sort_by { |k, v| k }, h.each.sort_by { |k, v| k }
|
185
|
+
#
|
184
186
|
values = []
|
185
187
|
h.each do |k, v|
|
186
188
|
values << [k, v]
|
@@ -188,6 +190,36 @@ class TestRadixTree < Test::Unit::TestCase
|
|
188
190
|
assert_equal s.to_a.sort_by { |k, v| k }, values.sort_by { |k, v| k }
|
189
191
|
end
|
190
192
|
|
193
|
+
def test_each_key
|
194
|
+
h = RadixTree.new
|
195
|
+
s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
|
196
|
+
s.each do |k, v|
|
197
|
+
h[k] = v
|
198
|
+
end
|
199
|
+
assert_equal s.keys.sort, h.each_key.sort
|
200
|
+
#
|
201
|
+
values = []
|
202
|
+
h.each_key do |k|
|
203
|
+
values << k
|
204
|
+
end
|
205
|
+
assert_equal s.keys.sort, values.sort
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_each_value
|
209
|
+
h = RadixTree.new
|
210
|
+
s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6, 'azzzzz' => 6 }
|
211
|
+
s.each do |k, v|
|
212
|
+
h[k] = v
|
213
|
+
end
|
214
|
+
assert_equal s.values.sort, h.each_value.sort
|
215
|
+
#
|
216
|
+
values = []
|
217
|
+
h.each_value do |v|
|
218
|
+
values << v
|
219
|
+
end
|
220
|
+
assert_equal s.values.sort, values.sort
|
221
|
+
end
|
222
|
+
|
191
223
|
def test_keys
|
192
224
|
h = RadixTree.new
|
193
225
|
s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
|
@@ -239,6 +271,27 @@ class TestRadixTree < Test::Unit::TestCase
|
|
239
271
|
assert h['baz'].object_id != h['qux'].object_id
|
240
272
|
end
|
241
273
|
|
274
|
+
def test_to_hash
|
275
|
+
h = RadixTree.new
|
276
|
+
s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
|
277
|
+
s.each do |k, v|
|
278
|
+
h[k] = v
|
279
|
+
end
|
280
|
+
assert_equal s, h.to_hash
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_clear
|
284
|
+
h = RadixTree.new
|
285
|
+
s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
|
286
|
+
s.each do |k, v|
|
287
|
+
h[k] = v
|
288
|
+
end
|
289
|
+
assert_equal s, h.to_hash
|
290
|
+
h.clear
|
291
|
+
assert_equal 0, h.size
|
292
|
+
assert h.to_hash.empty?
|
293
|
+
end
|
294
|
+
|
242
295
|
if RUBY_VERSION >= '1.9.0'
|
243
296
|
def test_encoding
|
244
297
|
h = RadixTree.new
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radix_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Hiroshi Nakamura
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-06 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: nahi@ruby-lang.org
|
@@ -33,12 +33,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
33
|
- - ! '>='
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: '0'
|
36
|
+
segments:
|
37
|
+
- 0
|
38
|
+
hash: -966188071225850011
|
36
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
40
|
none: false
|
38
41
|
requirements:
|
39
|
-
- - ! '
|
42
|
+
- - ! '>='
|
40
43
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
44
|
+
version: '0'
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
hash: -966188071225850011
|
42
48
|
requirements: []
|
43
49
|
rubyforge_project:
|
44
50
|
rubygems_version: 1.8.11
|