Class: SkillExtractor::KeywordMatcher
- Inherits:
-
Object
- Object
- SkillExtractor::KeywordMatcher
- Defined in:
- lib/skill_extractor/matcher.rb
Constant Summary collapse
- KEYWORD =
:__keyword__- WORD_CHARS =
("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + ["_"]
- WORD_SET =
WORD_CHARS.to_h { |c| [c, true] }.freeze
Instance Method Summary collapse
- #add(keyword) ⇒ Object
-
#extract(sentence) ⇒ Object
Returns [[keyword, start, end], ...] spans, matching FlashText exactly.
-
#initialize(keywords = []) ⇒ KeywordMatcher
constructor
A new instance of KeywordMatcher.
Constructor Details
#initialize(keywords = []) ⇒ KeywordMatcher
Returns a new instance of KeywordMatcher.
11 12 13 14 |
# File 'lib/skill_extractor/matcher.rb', line 11 def initialize(keywords = []) @trie = {} keywords.each { |kw| add(kw) } end |
Instance Method Details
#add(keyword) ⇒ Object
16 17 18 19 20 21 22 23 |
# File 'lib/skill_extractor/matcher.rb', line 16 def add(keyword) node = @trie kw = keyword.downcase kw.each_char do |ch| node = (node[ch] ||= {}) end node[KEYWORD] = kw end |
#extract(sentence) ⇒ Object
Returns [[keyword, start, end], ...] spans, matching FlashText exactly.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/skill_extractor/matcher.rb', line 26 def extract(sentence) out = [] return out if sentence.nil? || sentence.empty? sentence = sentence.downcase chars = sentence.chars current = @trie seq_start = 0 seq_end = 0 reset = false idx = 0 n = chars.length while idx < n ch = chars[idx] if !WORD_SET[ch] if current.key?(KEYWORD) || current.key?(ch) longest = nil longer_found = false if current.key?(KEYWORD) longest = current[KEYWORD] seq_end = idx end if current.key?(ch) cont = current[ch] idy = idx + 1 broke = false while idy < n inner = chars[idy] if !WORD_SET[inner] && cont.key?(KEYWORD) longest = cont[KEYWORD] seq_end = idy longer_found = true end if cont.key?(inner) cont = cont[inner] else broke = true break end idy += 1 end if !broke && cont.key?(KEYWORD) longest = cont[KEYWORD] seq_end = idy longer_found = true end idx = seq_end if longer_found end current = @trie out << [longest, seq_start, idx] if longest reset = true else current = @trie reset = true end elsif current.key?(ch) current = current[ch] else current = @trie reset = true idy = idx + 1 while idy < n break unless WORD_SET[chars[idy]] idy += 1 end idx = idy end if idx + 1 >= n && current.key?(KEYWORD) out << [current[KEYWORD], seq_start, n] end idx += 1 if reset reset = false seq_start = idx end end out end |