trie_matcher 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/lib/trie_matcher/pattern_matcher.rb +37 -0
- data/lib/trie_matcher/version.rb +1 -1
- data/lib/trie_matcher.rb +23 -9
- data/spec/trie_matcher_spec.rb +7 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5315d69c65616a5d7ff6d608f1bdeb6584ac1907
|
4
|
+
data.tar.gz: 97ee1b5ec00f18bd74d1c8773c593a6a02e8ce56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7f960eb2dc46fab205c154ab44fb1159b2a70c4d0a434dd34e4af3de12529dc58b3165525d06f5fe5eaf639fcade2e95c183fb26d92f890414f4d6e23ca3a28
|
7
|
+
data.tar.gz: 46b3096cce0312b9b2ca9c76f1054278b042f3d3338cf16dcefa02e44ae79e2b2b5da3436f77a4c846017736a9de9037495e2a90a6e29eb471eda2e2c8851aef
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path("../trie_matcher", __dir__)
|
2
|
+
|
3
|
+
# Convenience class for matching specific patterns, accelerated by a static prefix.
|
4
|
+
#
|
5
|
+
# This is extremely useful for matching complex patterns such as user agents or url routes
|
6
|
+
class TrieMatcher::PatternMatcher
|
7
|
+
# Build an empty pattern matcher
|
8
|
+
def initialize
|
9
|
+
@trie = TrieMatcher.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Register a pattern, along with a static prefix
|
13
|
+
#
|
14
|
+
# @param prefix [String] a static prefix that indicates this pattern should be tested
|
15
|
+
# @param pattern [Regexp] a pattern to test against
|
16
|
+
# @yield [match] executed if a positive match is made
|
17
|
+
# @yieldparam match [MatchData] the match data from the pattern
|
18
|
+
def add_pattern(prefix, pattern, &block)
|
19
|
+
@trie[prefix] ||= {}
|
20
|
+
@trie[prefix][pattern] = block
|
21
|
+
end
|
22
|
+
|
23
|
+
# Match a string against all registered patterns efficiently.
|
24
|
+
#
|
25
|
+
# Calls the block registered against any matching pattern, and passes in the match data
|
26
|
+
#
|
27
|
+
# @param string [String] the string to match against
|
28
|
+
def match(string)
|
29
|
+
result = @trie[string]
|
30
|
+
return nil unless result
|
31
|
+
result.each do |pattern, block|
|
32
|
+
match = pattern.match(string)
|
33
|
+
block.call(match) if match
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/lib/trie_matcher/version.rb
CHANGED
data/lib/trie_matcher.rb
CHANGED
@@ -1,30 +1,43 @@
|
|
1
1
|
require File.expand_path("trie_matcher/version", __dir__)
|
2
2
|
|
3
|
+
# Trie implementation that acts as a weak mapping
|
4
|
+
#
|
5
|
+
# Values can be stored for a given prefix, and are returned for the longest prefix.
|
6
|
+
# Lookup searches for longer prefixes optimistically, so saturated tries with many lexemes in them will be less efficient
|
3
7
|
class TrieMatcher
|
8
|
+
# Build an empty trie
|
4
9
|
def initialize
|
5
10
|
@root = { nodes: {}, value: nil}
|
6
11
|
end
|
7
12
|
|
8
|
-
|
13
|
+
# Store a prefix in the trie, and associate a value with it
|
14
|
+
#
|
15
|
+
# @param prefix [String]
|
16
|
+
# @param value [Object] a value to return if prefix is the longest prefix on lookup
|
17
|
+
# @return [Object] the value that was set
|
18
|
+
def []=(prefix, value)
|
9
19
|
current = @root
|
10
|
-
|
20
|
+
current_prefix = prefix
|
11
21
|
|
12
|
-
while
|
13
|
-
current,
|
22
|
+
while current_prefix != ""
|
23
|
+
current, current_prefix = find_canididate_insertion_node(current, current_prefix)
|
14
24
|
end
|
15
25
|
|
16
26
|
current[:value] = value
|
17
27
|
return value
|
18
28
|
end
|
19
29
|
|
20
|
-
|
21
|
-
|
30
|
+
# Perform a prefix search. Will return the value associated with the longest prefix
|
31
|
+
#
|
32
|
+
# @param prefix [String] what to check for a prefix in
|
33
|
+
# @return [Object] the value associated with the longest matching prefix in this trie
|
34
|
+
def [](prefix)
|
22
35
|
current = @root
|
23
|
-
|
36
|
+
current_prefix = prefix
|
24
37
|
|
25
|
-
while current != nil &&
|
38
|
+
while current != nil && current_prefix != ""
|
26
39
|
previous = current
|
27
|
-
current,
|
40
|
+
current, current_prefix = next_node(current, current_prefix)
|
28
41
|
end
|
29
42
|
|
30
43
|
return current[:value] if current
|
@@ -32,6 +45,7 @@ class TrieMatcher
|
|
32
45
|
end
|
33
46
|
|
34
47
|
private
|
48
|
+
# get the node for insertion, splitting shared prefixes into subnodes if necessary
|
35
49
|
def find_canididate_insertion_node(current, key)
|
36
50
|
# look for a common prefix
|
37
51
|
current[:nodes].keys.find do |prefix|
|
data/spec/trie_matcher_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trie_matcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Karas
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
69
|
- lib/trie_matcher.rb
|
70
|
+
- lib/trie_matcher/pattern_matcher.rb
|
70
71
|
- lib/trie_matcher/version.rb
|
71
72
|
- spec/spec_helper.rb
|
72
73
|
- spec/trie_matcher_spec.rb
|