fuzzy_hash 0.0.3

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,63 @@
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
+ s.rubyforge_project = 'fuzzyhash' # This line would be new
11
+ end
12
+ rescue LoadError
13
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
14
+ end
15
+
16
+ # These are new tasks
17
+ begin
18
+ require 'rake/contrib/sshpublisher'
19
+ namespace :rubyforge do
20
+
21
+ desc "Release gem and RDoc documentation to RubyForge"
22
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
23
+
24
+ namespace :release do
25
+ desc "Publish RDoc to RubyForge."
26
+ task :docs => [:rdoc] do
27
+ config = YAML.load(
28
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
29
+ )
30
+
31
+ host = "#{config['username']}@rubyforge.org"
32
+ remote_dir = "/var/www/gforge-projects/fuzzyhash/"
33
+ local_dir = 'rdoc'
34
+
35
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
36
+ end
37
+ end
38
+ end
39
+ rescue LoadError
40
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
41
+ end
42
+
43
+
44
+ require 'spec'
45
+ require 'spec/rake/spectask'
46
+ task :spec => 'spec:all'
47
+ namespace(:spec) do
48
+ Spec::Rake::SpecTask.new(:all) do |t|
49
+ t.spec_opts ||= []
50
+ t.spec_opts << "-rubygems"
51
+ t.spec_opts << "--options" << "spec/spec.opts"
52
+ t.spec_files = FileList['spec/**/*_spec.rb']
53
+ end
54
+
55
+ end
56
+
57
+ desc "Run all examples with RCov"
58
+ Spec::Rake::SpecTask.new('spec_with_rcov') do |t|
59
+ t.spec_files = FileList['spec/**/*.rb']
60
+ t.rcov = true
61
+ t.rcov_opts = ['--exclude', 'spec']
62
+ end
63
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 3
3
+ :major: 0
4
+ :minor: 0
data/lib/fuzzy_hash.rb ADDED
@@ -0,0 +1,87 @@
1
+ class FuzzyHash
2
+
3
+ def initialize(init_hash = nil)
4
+ @regexes = []
5
+ @hash_reverse = {}
6
+ @regexes_reverse = {}
7
+ @hash = {}
8
+ init_hash.each{ |key,value| self[key] = value } if init_hash
9
+ end
10
+
11
+ def clear
12
+ @hash.clear
13
+ @regexes.clear
14
+ @hash_reverse.clear
15
+ @regexes_reverse.clear
16
+ end
17
+
18
+ def ==(o)
19
+ o.instance_variable_get(:@hash) == @hash &&
20
+ o.instance_variable_get(:@regexes) == @regexes
21
+ end
22
+
23
+ def empty?
24
+ @hash.empty? && @regexes.empty?
25
+ end
26
+
27
+ def keys
28
+ @hash.keys + @regexes.collect{|r| r.first}
29
+ end
30
+
31
+ def values
32
+ @hash.values + @regexes.collect{|r| r.last}
33
+ end
34
+
35
+ def each
36
+ @hash.each{|k,v| yield k,v }
37
+ @regexes.each{|v| yield v.first, v.last }
38
+ end
39
+
40
+ def delete_value(value)
41
+ @hash.delete(@hash_reverse[value]) || ((rr = @regexes_reverse[value]) && @regexes.delete_at(rr[0]))
42
+ end
43
+
44
+ def []=(key, value)
45
+ case key
46
+ when Regexp
47
+ @regexes << [key, value]
48
+ @regex_test = nil
49
+ @regexes_reverse[value] = [@regexes.size - 1, key, value]
50
+ else
51
+ @hash[key] = value
52
+ @hash_reverse[value] = key
53
+ end
54
+ end
55
+
56
+ def replace(src, dest)
57
+ if @hash_reverse.key?(src)
58
+ key = @hash_reverse[src]
59
+ @hash[key] = dest
60
+ @hash_reverse.delete(src)
61
+ @hash_reverse[dest] = key
62
+ elsif @regexes_reverse.key?(src)
63
+ key = @regexes_reverse[src]
64
+ @regexes[rkey[0]] = [rkey[1], dest]
65
+ @regexes_reverse.delete(src)
66
+ @regexes_reverse[dest] = [rkey[0], rkey[1], dest]
67
+ end
68
+ end
69
+
70
+ def [](key)
71
+ @hash.key?(key) ? @hash[key] : regex_lookup(key)
72
+ end
73
+
74
+ private
75
+ def regex_test
76
+ @regex_test ||= Regexp.new(@regexes.collect{|r| "(#{r[0]})"} * '|')
77
+ end
78
+
79
+ def regex_lookup(key)
80
+ if !@regexes.empty? && key.is_a?(String) && (data = regex_test.match(key))
81
+ (data_array = data.to_a).each_index do |i|
82
+ break @regexes[i].last if data_array.at(i+1)
83
+ end
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,106 @@
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 allow boolean keys" do
33
+ l = FuzzyHash.new
34
+ l[false] = 'false'
35
+ l[true] = 'true'
36
+ l[/.*/] = 'everything else'
37
+ l[true].should == 'true'
38
+ l[false].should == 'false'
39
+ l['false'].should == 'everything else'
40
+ end
41
+
42
+ it "should pick between the correct regex" do
43
+ hash = FuzzyHash.new
44
+ hash[/^\d+$/] = 'number'
45
+ hash[/.*/] = 'something'
46
+ hash['123asd'].should == 'something'
47
+ end
48
+
49
+ it "should be able to delete by value for hash" do
50
+ l = FuzzyHash.new
51
+ l[nil] = 'qwe2'
52
+ l['asd'] = 'qwe'
53
+ l['asd'].should == 'qwe'
54
+ l[nil].should == 'qwe2'
55
+ l.delete_value('qwe2')
56
+ l[nil].should == nil
57
+ end
58
+
59
+ it "should be able to delete by value for regex" do
60
+ l = FuzzyHash.new
61
+ l[/qwe.*/] = 'qwe2'
62
+ l['asd'] = 'qwe'
63
+ l['asd'].should == 'qwe'
64
+ l['qweasd'].should == 'qwe2'
65
+ l.delete_value('qwe2')
66
+ l['qweasd'].should == nil
67
+ end
68
+
69
+ it "should iterate through the keys" do
70
+ l = FuzzyHash.new
71
+ l[/qwe.*/] = 'qwe2'
72
+ l['asd'] = 'qwe'
73
+ l['zxc'] = 'qwe'
74
+ ([/qwe.*/,'asd','zxc'] & l.keys).size.should == 3
75
+ end
76
+
77
+ it "should iterate through the values" do
78
+ l = FuzzyHash.new
79
+ l[/qwe.*/] = 'qwe2'
80
+ l['asd'] = 'qwe'
81
+ l['zxc'] = 'qwelkj'
82
+ (['qwe2','qwe','qwelkj'] & l.values).size.should == 3
83
+ end
84
+
85
+ it "should clear" do
86
+ l = FuzzyHash.new
87
+ l[/qwe.*/] = 'qwe2'
88
+ l['asd'] = 'qwe'
89
+ l['zxc'] = 'qwelkj'
90
+ l.clear
91
+ l.empty?.should == true
92
+ end
93
+
94
+ it "should ==" do
95
+ l_1 = FuzzyHash.new
96
+ l_1[/qwe.*/] = 'qwe2'
97
+ l_1['asd'] = 'qwelkj'
98
+ l_1['zxc'] = 'qwe'
99
+ l_2 = FuzzyHash.new
100
+ l_2['zxc'] = 'qwe'
101
+ l_2['asd'] = 'qwelkj'
102
+ l_2[/qwe.*/] = 'qwe2'
103
+ l_1.should == l_2
104
+ end
105
+
106
+ 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,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fuzzy_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Hull
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-16 00:00:00 -04: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
+ - README.rdoc
27
+ - Rakefile
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
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: fuzzyhash
56
+ rubygems_version: 1.3.4
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: A weird hash with special semantics for regex keys
60
+ test_files:
61
+ - spec/fuzzy_hash_spec.rb