joshbuddy-fuzzy_hash 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt ADDED
@@ -0,0 +1,5 @@
1
+ Manifest.txt
2
+ Rakefile
3
+ fuzzy_hash.gemspec
4
+ lib/fuzzy_hash.rb
5
+ spec/lookup_spec.rb
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
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
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
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace
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
+