fuzzyhash 0.0.7 → 0.0.8
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/VERSION.yml +1 -1
- data/lib/fuzzy_hash.rb +70 -47
- data/spec/fuzzy_hash_spec.rb +27 -0
- metadata +2 -2
data/VERSION.yml
CHANGED
data/lib/fuzzy_hash.rb
CHANGED
@@ -1,112 +1,135 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
class FuzzyHash
|
4
|
+
|
5
|
+
def self.always_fuzzy(init_hash = nil)
|
6
|
+
hash = new(init_hash)
|
7
|
+
hash.classes_to_fuzz = nil
|
8
|
+
hash
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :classes_to_fuzz
|
2
12
|
|
3
|
-
def initialize(init_hash = nil)
|
4
|
-
@
|
13
|
+
def initialize(init_hash = nil, classes_to_fuzz = nil)
|
14
|
+
@fuzzies = []
|
5
15
|
@hash_reverse = {}
|
6
|
-
@
|
16
|
+
@fuzzies_reverse = {}
|
7
17
|
@hash = {}
|
18
|
+
@classes_to_fuzz = classes_to_fuzz || [Regexp]
|
19
|
+
@classes_to_fuzz = Set.new(@classes_to_fuzz)
|
8
20
|
init_hash.each{ |key,value| self[key] = value } if init_hash
|
9
21
|
end
|
10
22
|
|
11
23
|
def clear
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
24
|
+
hash.clear
|
25
|
+
fuzzies.clear
|
26
|
+
hash_reverse.clear
|
27
|
+
fuzzies_reverse.clear
|
16
28
|
end
|
17
29
|
|
18
30
|
def size
|
19
|
-
|
31
|
+
hash.size + fuzzies.size
|
20
32
|
end
|
21
33
|
alias_method :count, :size
|
22
34
|
|
23
35
|
|
24
36
|
def ==(o)
|
25
37
|
o.is_a?(FuzzyHash)
|
26
|
-
o.
|
27
|
-
o.
|
38
|
+
o.send(:hash) == hash &&
|
39
|
+
o.send(:fuzzies) == fuzzies
|
28
40
|
end
|
29
41
|
|
30
42
|
def empty?
|
31
|
-
|
43
|
+
hash.empty? && fuzzies.empty?
|
32
44
|
end
|
33
45
|
|
34
46
|
def keys
|
35
|
-
|
47
|
+
hash.keys + fuzzies.collect{|r| r.first}
|
36
48
|
end
|
37
49
|
|
38
50
|
def values
|
39
|
-
|
51
|
+
hash.values + fuzzies.collect{|r| r.last}
|
40
52
|
end
|
41
53
|
|
42
54
|
def each
|
43
|
-
|
44
|
-
|
55
|
+
hash.each{|k,v| yield k,v }
|
56
|
+
fuzzies.each{|v| yield v.first, v.last }
|
45
57
|
end
|
46
58
|
|
47
59
|
def delete_value(value)
|
48
|
-
|
60
|
+
hash.delete(hash_reverse[value]) || ((rr = fuzzies_reverse[value]) && fuzzies.delete_at(rr[0]))
|
49
61
|
end
|
50
62
|
|
51
63
|
def []=(key, value)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
64
|
+
if classes_to_fuzz.nil? || classes_to_fuzz.include?(key.class)
|
65
|
+
fuzzies.delete_if{|f| f.first.hash == key.hash}
|
66
|
+
fuzzies_reverse.delete_if{|k, v| v.hash == key.hash}
|
67
|
+
|
68
|
+
fuzzies << [key, value]
|
69
|
+
reset_fuzz_test!
|
70
|
+
fuzzies_reverse[value] = [fuzzies.size - 1, key, value]
|
57
71
|
else
|
58
|
-
|
59
|
-
|
72
|
+
hash[key] = value
|
73
|
+
hash_reverse.delete_if{|k,v| v.hash == key.hash}
|
74
|
+
hash_reverse[value] = key
|
60
75
|
end
|
61
76
|
value
|
62
77
|
end
|
63
78
|
|
64
79
|
def replace(src, dest)
|
65
|
-
if
|
66
|
-
key =
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
elsif
|
71
|
-
key =
|
72
|
-
|
73
|
-
|
74
|
-
|
80
|
+
if hash_reverse.key?(src)
|
81
|
+
key = hash_reverse[src]
|
82
|
+
hash[key] = dest
|
83
|
+
hash_reverse.delete(src)
|
84
|
+
hash_reverse[dest] = key
|
85
|
+
elsif fuzzies_reverse.key?(src)
|
86
|
+
key = fuzzies_reverse[src]
|
87
|
+
fuzzies[rkey[0]] = [rkey[1], dest]
|
88
|
+
fuzzies_reverse.delete(src)
|
89
|
+
fuzzies_reverse[dest] = [rkey[0], rkey[1], dest]
|
75
90
|
end
|
76
91
|
end
|
77
92
|
|
78
93
|
def [](key)
|
79
|
-
|
94
|
+
hash.key?(key) ? hash[key] : (lookup = fuzzy_lookup(key)) && lookup && lookup.first
|
80
95
|
end
|
81
96
|
|
82
97
|
def match_with_result(key)
|
83
|
-
if
|
84
|
-
[
|
98
|
+
if hash.key?(key)
|
99
|
+
[hash[key], key]
|
85
100
|
else
|
86
|
-
|
101
|
+
fuzzy_lookup(key)
|
87
102
|
end
|
88
103
|
end
|
89
104
|
|
90
105
|
private
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
106
|
+
attr_reader :fuzzies, :hash_reverse, :fuzzies_reverse, :hash
|
107
|
+
attr_writer :fuzz_test
|
108
|
+
|
109
|
+
def reset_fuzz_test!
|
110
|
+
self.fuzz_test = nil
|
111
|
+
end
|
112
|
+
|
113
|
+
def fuzz_test
|
114
|
+
unless @fuzz_test
|
115
|
+
@fuzz_test = Object.new
|
116
|
+
@fuzz_test.instance_variable_set(:'@fuzzies', fuzzies)
|
95
117
|
method = "
|
96
118
|
def match(str)
|
97
119
|
case str
|
98
120
|
"
|
99
|
-
|
100
|
-
method << "when #{reg.first.inspect}: [@
|
121
|
+
fuzzies.each_with_index do |reg, index|
|
122
|
+
method << "when #{reg.first.inspect}: [@fuzzies[#{index}][1], str]\n"
|
101
123
|
end
|
102
124
|
method << "end\nend\n"
|
103
|
-
|
125
|
+
|
126
|
+
@fuzz_test.instance_eval method
|
104
127
|
end
|
105
|
-
@
|
128
|
+
@fuzz_test
|
106
129
|
end
|
107
130
|
|
108
|
-
def
|
109
|
-
if
|
131
|
+
def fuzzy_lookup(key)
|
132
|
+
if !fuzzies.empty? && (value = fuzz_test.match(key))
|
110
133
|
value
|
111
134
|
end
|
112
135
|
end
|
data/spec/fuzzy_hash_spec.rb
CHANGED
@@ -8,12 +8,26 @@ describe "Fuzzy hash" do
|
|
8
8
|
l['asd'].should == 'qwe'
|
9
9
|
end
|
10
10
|
|
11
|
+
it "should accept strings, but the second time you set the same string, it should overwrite" do
|
12
|
+
l = FuzzyHash.new
|
13
|
+
l['asd'] = 'asd'
|
14
|
+
l['asd'] = 'qwe'
|
15
|
+
l['asd'].should == 'qwe'
|
16
|
+
end
|
17
|
+
|
11
18
|
it "should accept regexs too" do
|
12
19
|
l = FuzzyHash.new
|
13
20
|
l[/asd.*/] = 'qwe'
|
14
21
|
l['asdqweasd'].should == 'qwe'
|
15
22
|
end
|
16
23
|
|
24
|
+
it "should accept regexs too, but the second time you set the same regex, it should overwrite" do
|
25
|
+
l = FuzzyHash.new
|
26
|
+
l[/asd/] = 'asd'
|
27
|
+
l[/asd/] = 'qwe'
|
28
|
+
l['asdqweasd'].should == 'qwe'
|
29
|
+
end
|
30
|
+
|
17
31
|
it "should accept regexs too with the match" do
|
18
32
|
l = FuzzyHash.new
|
19
33
|
l[/asd.*/] = 'qwe'
|
@@ -45,6 +59,19 @@ describe "Fuzzy hash" do
|
|
45
59
|
l['false'].should == 'everything else'
|
46
60
|
end
|
47
61
|
|
62
|
+
it "always fuzzy should accept .. well.. anything" do
|
63
|
+
l = FuzzyHash.always_fuzzy
|
64
|
+
l[1..3] = '1 to 3'
|
65
|
+
l[4] = 'four'
|
66
|
+
l[5..10] = '5 and up'
|
67
|
+
l[/.*/] = 'whatev'
|
68
|
+
|
69
|
+
l[2].should == '1 to 3'
|
70
|
+
l[4].should == 'four'
|
71
|
+
l[8].should == '5 and up'
|
72
|
+
l['something'].should == 'whatev'
|
73
|
+
end
|
74
|
+
|
48
75
|
it "should pick between the correct regex" do
|
49
76
|
hash = FuzzyHash.new
|
50
77
|
hash[/^\d+$/] = 'number'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fuzzyhash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Hull
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-11 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|