stringtree 0.1.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.
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.travis.yml +2 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +95 -0
- data/Rakefile +13 -0
- data/examples/demo.rb +82 -0
- data/examples/dictionary.txt +61217 -0
- data/examples/hamlet.txt +5590 -0
- data/examples/warandpeace.txt +64950 -0
- data/hamlet.tokens.txt +31262 -0
- data/lib/stringtree/item.rb +28 -0
- data/lib/stringtree/node.rb +216 -0
- data/lib/stringtree/tree.rb +98 -0
- data/lib/stringtree/version.rb +5 -0
- data/lib/stringtree.rb +6 -0
- data/spec/item_spec.rb +32 -0
- data/spec/node_spec.rb +187 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tree_spec.rb +266 -0
- data/stringtree.gemspec +26 -0
- data/warandpeace.tokens.txt +572121 -0
- metadata +220 -0
data/spec/tree_spec.rb
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StringTree::Tree do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "should initialize correctly" do
|
6
|
+
@tree = StringTree::Tree.new
|
7
|
+
expect(@tree.root).to be_nil()
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#add' do
|
12
|
+
it 'should produce the correct node tree' do
|
13
|
+
inst = StringTree::Tree.new
|
14
|
+
|
15
|
+
inst.add("OneX",5)
|
16
|
+
inst.add("TwoX",3)
|
17
|
+
inst.add("TenX",10)
|
18
|
+
|
19
|
+
expect(inst.root.char).to eq("O")
|
20
|
+
expect(inst.root.right.char).to eq("T")
|
21
|
+
expect(inst.root.left).to be_nil()
|
22
|
+
expect(inst.root.right.down.char).to eq("w")
|
23
|
+
expect(inst.root.right.down.left.char).to eq("e")
|
24
|
+
expect(inst.root.right.down.right).to be_nil()
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should overwrite value if key exists' do
|
28
|
+
inst = StringTree::Tree.new
|
29
|
+
|
30
|
+
inst.add("OneX",5)
|
31
|
+
inst.add("TwoX",3)
|
32
|
+
inst.add("TenX",10)
|
33
|
+
|
34
|
+
expect(inst.find("TenX")).to eq(10)
|
35
|
+
|
36
|
+
inst.add("TenX",15)
|
37
|
+
expect(inst.find("TenX")).to eq(15)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#find' do
|
42
|
+
it 'should return nil if tree empty' do
|
43
|
+
inst = StringTree::Tree.new
|
44
|
+
|
45
|
+
expect(inst.find("TwoX")).to be_nil()
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should return correct value' do
|
49
|
+
inst = StringTree::Tree.new
|
50
|
+
|
51
|
+
inst.add("OneX",5)
|
52
|
+
inst.add("TwoX",3)
|
53
|
+
inst.add("TenX",10)
|
54
|
+
|
55
|
+
expect(inst.find("TwoX")).to eq(3)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should return nil if not found' do
|
59
|
+
inst = StringTree::Tree.new
|
60
|
+
|
61
|
+
inst.add("OneX",5)
|
62
|
+
inst.add("TwoX",3)
|
63
|
+
inst.add("TenX",10)
|
64
|
+
|
65
|
+
expect(inst.find("FiveX")).to be_nil()
|
66
|
+
expect(inst.find("O")).to be_nil()
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#has_key?' do
|
71
|
+
it 'should return false if tree empty' do
|
72
|
+
inst = StringTree::Tree.new
|
73
|
+
expect(inst.has_key?("TwoX")).to be(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return correct results if found' do
|
77
|
+
inst = StringTree::Tree.new
|
78
|
+
|
79
|
+
inst.add("OneX",5)
|
80
|
+
inst.add("TwoX",3)
|
81
|
+
inst.add("TenX",10)
|
82
|
+
|
83
|
+
expect(inst.has_key?("OneX")).to be(true)
|
84
|
+
expect(inst.has_key?("TwoX")).to be(true)
|
85
|
+
expect(inst.has_key?("TenX")).to be(true)
|
86
|
+
expect(inst.has_key?("O")).to be(false)
|
87
|
+
expect(inst.has_key?("Two")).to be(false)
|
88
|
+
expect(inst.has_key?("OTwo")).to be(false)
|
89
|
+
expect(inst.has_key?("OneXX")).to be(false)
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#partials' do
|
93
|
+
it 'should return correct results if found' do
|
94
|
+
inst = StringTree::Tree.new
|
95
|
+
inst.add('ant',1)
|
96
|
+
inst.add('antler',2)
|
97
|
+
inst.add('deer',3)
|
98
|
+
inst.add('anthropic',4)
|
99
|
+
inst.add('beer',5)
|
100
|
+
|
101
|
+
expect(inst.partials('ant')).to eq(["antler", "anthropic"])
|
102
|
+
expect(inst.partials('be')).to eq(["beer"])
|
103
|
+
expect(inst.partials('d')).to eq(["deer"])
|
104
|
+
expect(inst.partials('a')).to eq(["antler", "anthropic", "ant"])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#optimize!' do
|
109
|
+
it 'should balance nodes' do
|
110
|
+
inst = StringTree::Tree.new
|
111
|
+
inst.add('abaft',2)
|
112
|
+
inst.add('abalone',3)
|
113
|
+
inst.add('abandon',4)
|
114
|
+
inst.add('abandoned',5)
|
115
|
+
inst.add('mystagogue',6)
|
116
|
+
inst.add('mystagogy',7)
|
117
|
+
inst.add('mysteries',8)
|
118
|
+
inst.add('mysterious',9)
|
119
|
+
inst.add('zestful',10)
|
120
|
+
inst.add('zestfully',11)
|
121
|
+
inst.add('zestfulness',12)
|
122
|
+
inst.add('zesty',13)
|
123
|
+
|
124
|
+
expect(inst.root.char).to eq('a')
|
125
|
+
expect(inst.root.count(:left)).to eq(1)
|
126
|
+
expect(inst.root.count(:right)).to eq(3)
|
127
|
+
expect(inst.root.down.char).to eq('b')
|
128
|
+
expect(inst.root.down.count(:left)).to eq(1)
|
129
|
+
expect(inst.root.down.count(:right)).to eq(1)
|
130
|
+
expect(inst.root.down.down.char).to eq('a')
|
131
|
+
expect(inst.root.down.down.count(:left)).to eq(1)
|
132
|
+
expect(inst.root.down.down.count(:right)).to eq(1)
|
133
|
+
|
134
|
+
inst.optimize!
|
135
|
+
|
136
|
+
expect(inst.root.char).to eq('m')
|
137
|
+
expect(inst.root.count(:left)).to eq(2)
|
138
|
+
expect(inst.root.count(:right)).to eq(2)
|
139
|
+
expect(inst.root.down.char).to eq('y')
|
140
|
+
expect(inst.root.down.count(:left)).to eq(1)
|
141
|
+
expect(inst.root.down.count(:right)).to eq(1)
|
142
|
+
expect(inst.root.down.down.char).to eq('s')
|
143
|
+
expect(inst.root.down.down.count(:left)).to eq(1)
|
144
|
+
expect(inst.root.down.down.count(:right)).to eq(1)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should not disturb normal behaviour' do
|
148
|
+
inst = StringTree::Tree.new
|
149
|
+
|
150
|
+
inst.add("OneX",5)
|
151
|
+
inst.add("TwoX",3)
|
152
|
+
inst.add("TenX",10)
|
153
|
+
inst.add("FifteenX",15)
|
154
|
+
|
155
|
+
inst.optimize!
|
156
|
+
|
157
|
+
expect(inst.find("OneX")).to eq(5)
|
158
|
+
expect(inst.find("TwoX")).to eq(3)
|
159
|
+
expect(inst.find("TenX")).to eq(10)
|
160
|
+
expect(inst.find("FifteenX")).to eq(15)
|
161
|
+
expect(inst.find("FiveX")).to be_nil()
|
162
|
+
expect(inst.find("O")).to be_nil()
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#match_all' do
|
167
|
+
it 'should tokenize properly' do
|
168
|
+
|
169
|
+
inst = StringTree::Tree.new
|
170
|
+
inst.add('test',1)
|
171
|
+
inst.add('foo',2)
|
172
|
+
inst.add('bar',3)
|
173
|
+
|
174
|
+
x = []
|
175
|
+
inst.match_all('the testing of foo should be bar for foo') { |match| x << match }
|
176
|
+
|
177
|
+
expect(x.length).to eq(4)
|
178
|
+
expect([x[0].offset,x[0].node.to_s,x[0].node.value]).to eq([4,'test',1])
|
179
|
+
expect([x[1].offset,x[1].node.to_s,x[1].node.value]).to eq([15,'foo',2])
|
180
|
+
expect([x[2].offset,x[2].node.to_s,x[2].node.value]).to eq([29,'bar',3])
|
181
|
+
expect([x[3].offset,x[3].node.to_s,x[3].node.value]).to eq([37,'foo',2])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#[]' do
|
186
|
+
it 'should return nil if tree empty' do
|
187
|
+
inst = StringTree::Tree.new
|
188
|
+
|
189
|
+
expect(inst["TwoX"]).to be_nil()
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should return like find' do
|
193
|
+
inst = StringTree::Tree.new
|
194
|
+
|
195
|
+
inst.add("OneX",5)
|
196
|
+
inst.add("TwoX",3)
|
197
|
+
inst.add("TenX",10)
|
198
|
+
|
199
|
+
expect(inst["TwoX"]).to eq(3)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should return nil if not found' do
|
203
|
+
inst = StringTree::Tree.new
|
204
|
+
|
205
|
+
inst.add("OneX",5)
|
206
|
+
inst.add("TwoX",3)
|
207
|
+
inst.add("TenX",10)
|
208
|
+
|
209
|
+
expect(inst["FiveX"]).to be_nil()
|
210
|
+
expect(inst["O"]).to be_nil()
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '#[]=]' do
|
215
|
+
it 'should produce the correct node tree like add' do
|
216
|
+
inst = StringTree::Tree.new
|
217
|
+
|
218
|
+
inst["OneX"] = 5
|
219
|
+
inst["TwoX"] = 3
|
220
|
+
inst["TenX"] = 10
|
221
|
+
|
222
|
+
expect(inst.root.char).to eq("O")
|
223
|
+
expect(inst.root.right.char).to eq("T")
|
224
|
+
expect(inst.root.left).to be_nil()
|
225
|
+
expect(inst.root.right.down.char).to eq("w")
|
226
|
+
expect(inst.root.right.down.left.char).to eq("e")
|
227
|
+
expect(inst.root.right.down.right).to be_nil()
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'should overwrite value if key exists' do
|
231
|
+
inst = StringTree::Tree.new
|
232
|
+
|
233
|
+
inst["OneX"] = 5
|
234
|
+
inst["TwoX"] = 3
|
235
|
+
inst["TenX"] = 10
|
236
|
+
|
237
|
+
expect(inst.find("TenX")).to eq(10)
|
238
|
+
|
239
|
+
inst.add("TenX",15)
|
240
|
+
expect(inst.find("TenX")).to eq(15)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe '#match_count' do
|
245
|
+
it 'should count properly' do
|
246
|
+
|
247
|
+
arr = {
|
248
|
+
"test"=>1,
|
249
|
+
"foo"=>2,
|
250
|
+
"bar"=>3,
|
251
|
+
}
|
252
|
+
inst = StringTree::Tree.new
|
253
|
+
|
254
|
+
arr.each do |k,v|
|
255
|
+
inst.add(k,v)
|
256
|
+
end
|
257
|
+
|
258
|
+
x = inst.match_count('the testing of foo should be bar for foo')
|
259
|
+
|
260
|
+
x.each do |k,v|
|
261
|
+
expect(k.value).to eq(arr[k.to_s])
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
data/stringtree.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/stringtree/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.authors = ["Tom Cully"]
|
6
|
+
s.email = ["tomhughcully@gmail.com"]
|
7
|
+
s.summary = 'A String Trie for Ruby allowing partial string searches'
|
8
|
+
s.description = 'stringtree is design to allow efficient partial string searches/autocomplete and tokenization'
|
9
|
+
s.homepage = "http://github.com/tomdionysus/stringtree-ruby"
|
10
|
+
s.required_ruby_version = '>= 1.9.3'
|
11
|
+
s.files = `git ls-files`.split($\)
|
12
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
13
|
+
s.name = "stringtree"
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
s.version = StringTree::VERSION
|
16
|
+
|
17
|
+
s.add_development_dependency "coveralls"
|
18
|
+
s.add_development_dependency "bundler", "~> 1.10"
|
19
|
+
s.add_development_dependency "rake", "~> 10.0"
|
20
|
+
s.add_development_dependency 'simplecov', '~> 0.10.0'
|
21
|
+
s.add_development_dependency 'simplecov-rcov', '~> 0.2'
|
22
|
+
s.add_development_dependency 'rdoc', '~> 4.1'
|
23
|
+
s.add_development_dependency 'sdoc', '~> 0.4'
|
24
|
+
s.add_development_dependency 'rspec', '~> 3.1'
|
25
|
+
s.add_development_dependency 'rspec-mocks', '~> 3.1'
|
26
|
+
end
|