joshbuddy-fuzzy_hash 0.0.1
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/Manifest.txt +5 -0
- data/README.rdoc +17 -0
- data/Rakefile +26 -0
- data/VERSION.yml +4 -0
- data/lib/fuzzy_hash.rb +88 -0
- data/spec/fuzzy_hash_spec.rb +96 -0
- data/spec/spec.opts +7 -0
- metadata +60 -0
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= Fuzzy Hash
|
2
|
+
|
3
|
+
This is useful when you want to have a lookup table that can either contain strings or regexes.
|
4
|
+
For instance, you might want a catch all for certain regexes that perform a certain logic.
|
5
|
+
|
6
|
+
>> hash = FuzzyHash.new
|
7
|
+
>> hash[/^\d+$/] = 'number'
|
8
|
+
>> hash[/.*/] = 'something'
|
9
|
+
>> hash['chunky'] = 'bacon'
|
10
|
+
>> hash['foo'] = 'vader'
|
11
|
+
|
12
|
+
>> hash['foo']
|
13
|
+
<< 'vader'
|
14
|
+
>> hash['food']
|
15
|
+
<< 'something'
|
16
|
+
>> hash['123']
|
17
|
+
<< 'number'
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |s|
|
4
|
+
s.name = "fuzzy_hash"
|
5
|
+
s.description = s.summary = "A weird hash with special semantics for regex keys"
|
6
|
+
s.email = "joshbuddy@gmail.com"
|
7
|
+
s.homepage = "http://github.com/joshbuddy/fuzzy_hash"
|
8
|
+
s.authors = ["Joshua Hull"]
|
9
|
+
s.files = FileList["[A-Z]*", "{lib,spec}/**/*"]
|
10
|
+
end
|
11
|
+
rescue LoadError
|
12
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'spec'
|
16
|
+
require 'spec/rake/spectask'
|
17
|
+
task :spec => 'spec:all'
|
18
|
+
namespace(:spec) do
|
19
|
+
Spec::Rake::SpecTask.new(:all) do |t|
|
20
|
+
t.spec_opts ||= []
|
21
|
+
t.spec_opts << "-rubygems"
|
22
|
+
t.spec_opts << "--options" << "spec/spec.opts"
|
23
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/VERSION.yml
ADDED
data/lib/fuzzy_hash.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
class FuzzyHash
|
2
|
+
|
3
|
+
Version = '0.0.1'
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@hash = {}
|
7
|
+
@regexes = []
|
8
|
+
@hash_reverse = {}
|
9
|
+
@regexes_reverse = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear
|
13
|
+
@hash.clear
|
14
|
+
@regexes.clear
|
15
|
+
@hash_reverse.clear
|
16
|
+
@regexes_reverse.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(o)
|
20
|
+
o.instance_variable_get(:@hash) == @hash &&
|
21
|
+
o.instance_variable_get(:@regexes) == @regexes
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
@hash.empty? && @regexes.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def keys
|
29
|
+
@hash.keys + @regexes.collect{|r| r.first}
|
30
|
+
end
|
31
|
+
|
32
|
+
def values
|
33
|
+
@hash.values + @regexes.collect{|r| r.last}
|
34
|
+
end
|
35
|
+
|
36
|
+
def each
|
37
|
+
@hash.each{|k,v| yield k,v }
|
38
|
+
@regexes.each{|v| yield v.first, v.last }
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_value(value)
|
42
|
+
@hash.delete(@hash_reverse[value]) || ((rr = @regexes_reverse[value]) && @regexes.delete_at(rr[0]))
|
43
|
+
end
|
44
|
+
|
45
|
+
def []=(key, value)
|
46
|
+
case key
|
47
|
+
when Regexp
|
48
|
+
@regexes << [key, value]
|
49
|
+
@regex_test = nil
|
50
|
+
@regexes_reverse[value] = [@regexes.size - 1, key, value]
|
51
|
+
else
|
52
|
+
@hash[key] = value
|
53
|
+
@hash_reverse[value] = key
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def replace(src, dest)
|
58
|
+
if @hash_reverse.key?(src)
|
59
|
+
key = @hash_reverse[src]
|
60
|
+
@hash[key] = dest
|
61
|
+
@hash_reverse.delete(src)
|
62
|
+
@hash_reverse[dest] = key
|
63
|
+
elsif @regexes_reverse.key?(src)
|
64
|
+
key = @regexes_reverse[src]
|
65
|
+
@regexes[rkey[0]] = [rkey[1], dest]
|
66
|
+
@regexes_reverse.delete(src)
|
67
|
+
@regexes_reverse[dest] = [rkey[0], rkey[1], dest]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def [](key)
|
72
|
+
@hash[key] || regex_lookup(key)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def regex_test
|
77
|
+
@regex_test ||= Regexp.new(@regexes.collect{|r| "(#{r[0]})"} * '|')
|
78
|
+
end
|
79
|
+
|
80
|
+
def regex_lookup(key)
|
81
|
+
if !@regexes.empty? && key.is_a?(String) && (data = regex_test.match(key))
|
82
|
+
(data_array = data.to_a).each_index do |i|
|
83
|
+
break @regexes[i].last if data_array.at(i+1)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'lib/fuzzy_hash'
|
2
|
+
|
3
|
+
describe "Fuzzy hash" do
|
4
|
+
|
5
|
+
it "should accept strings and retrieve based on them" do
|
6
|
+
l = FuzzyHash.new
|
7
|
+
l['asd'] = 'qwe'
|
8
|
+
l['asd'].should == 'qwe'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should accept regexs too" do
|
12
|
+
l = FuzzyHash.new
|
13
|
+
l[/asd.*/] = 'qwe'
|
14
|
+
l['asdqweasd'].should == 'qwe'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should prefer string to regex matches" do
|
18
|
+
l = FuzzyHash.new
|
19
|
+
l['asd'] = 'qwe2'
|
20
|
+
l[/asd.*/] = 'qwe'
|
21
|
+
l['asd'].should == 'qwe2'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should allow nil keys" do
|
25
|
+
l = FuzzyHash.new
|
26
|
+
l[nil] = 'qwe2'
|
27
|
+
l['asd'] = 'qwe'
|
28
|
+
l['asd'].should == 'qwe'
|
29
|
+
l[nil].should == 'qwe2'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should pick between the correct regex" do
|
33
|
+
hash = FuzzyHash.new
|
34
|
+
hash[/^\d+$/] = 'number'
|
35
|
+
hash[/.*/] = 'something'
|
36
|
+
hash['123asd'].should == 'something'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to delete by value for hash" do
|
40
|
+
l = FuzzyHash.new
|
41
|
+
l[nil] = 'qwe2'
|
42
|
+
l['asd'] = 'qwe'
|
43
|
+
l['asd'].should == 'qwe'
|
44
|
+
l[nil].should == 'qwe2'
|
45
|
+
l.delete_value('qwe2')
|
46
|
+
l[nil].should == nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should be able to delete by value for regex" do
|
50
|
+
l = FuzzyHash.new
|
51
|
+
l[/qwe.*/] = 'qwe2'
|
52
|
+
l['asd'] = 'qwe'
|
53
|
+
l['asd'].should == 'qwe'
|
54
|
+
l['qweasd'].should == 'qwe2'
|
55
|
+
l.delete_value('qwe2')
|
56
|
+
l['qweasd'].should == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should iterate through the keys" do
|
60
|
+
l = FuzzyHash.new
|
61
|
+
l[/qwe.*/] = 'qwe2'
|
62
|
+
l['asd'] = 'qwe'
|
63
|
+
l['zxc'] = 'qwe'
|
64
|
+
([/qwe.*/,'asd','zxc'] & l.keys).size.should == 3
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should iterate through the values" do
|
68
|
+
l = FuzzyHash.new
|
69
|
+
l[/qwe.*/] = 'qwe2'
|
70
|
+
l['asd'] = 'qwe'
|
71
|
+
l['zxc'] = 'qwelkj'
|
72
|
+
(['qwe2','qwe','qwelkj'] & l.values).size.should == 3
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should clear" do
|
76
|
+
l = FuzzyHash.new
|
77
|
+
l[/qwe.*/] = 'qwe2'
|
78
|
+
l['asd'] = 'qwe'
|
79
|
+
l['zxc'] = 'qwelkj'
|
80
|
+
l.clear
|
81
|
+
l.empty?.should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should ==" do
|
85
|
+
l_1 = FuzzyHash.new
|
86
|
+
l_1[/qwe.*/] = 'qwe2'
|
87
|
+
l_1['asd'] = 'qwelkj'
|
88
|
+
l_1['zxc'] = 'qwe'
|
89
|
+
l_2 = FuzzyHash.new
|
90
|
+
l_2['zxc'] = 'qwe'
|
91
|
+
l_2['asd'] = 'qwelkj'
|
92
|
+
l_2[/qwe.*/] = 'qwe2'
|
93
|
+
l_1.should == l_2
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
data/spec/spec.opts
ADDED
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: joshbuddy-fuzzy_hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Hull
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-26 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A weird hash with special semantics for regex keys
|
17
|
+
email: joshbuddy@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- Manifest.txt
|
26
|
+
- Rakefile
|
27
|
+
- README.rdoc
|
28
|
+
- VERSION.yml
|
29
|
+
- lib/fuzzy_hash.rb
|
30
|
+
- spec/fuzzy_hash_spec.rb
|
31
|
+
- spec/spec.opts
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/joshbuddy/fuzzy_hash
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --inline-source
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.2.0
|
56
|
+
signing_key:
|
57
|
+
specification_version: 2
|
58
|
+
summary: A weird hash with special semantics for regex keys
|
59
|
+
test_files: []
|
60
|
+
|