Created
December 29, 2015 13:13
-
-
Save tiagogeraldi/c040d9e39eb4c062ff3b to your computer and use it in GitHub Desktop.
Query searcher for string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
str = "I'd like to buy a Belina instead of a Pampa" | |
Search.new(query: 'Belina AND Pampa').test(str) #=> true | |
Search.new(query: 'Belin*').test(str) #=> true | |
Search.new(query: '"buy a Belina"').test(str) #=> true | |
Search.new(query: 'Belina -Pampa').test(str) #=> false | |
Search.new(query: 'Belina OR Corcel').test(str) #=> true | |
Search.new(query: '(Belina OR Corcel) AND Pampa').test(str) #=> true | |
Search.new(query: '(bananas OR mangos) AND frozen').test(str) #=> false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Search | |
attr_reader :query, :array_content, :string_content | |
def initialize(options) | |
@query = options[:query] | |
end | |
def test(str) | |
@string_content = str | |
@array_content = str.split(/[\s,.]+/) | |
matches? | |
end | |
private | |
def matches? | |
arguments = tokenize(process_parentheses(query)) | |
result = matching_with_operators(arguments) | |
result ||= matching_without_operators(arguments) | |
result | |
end | |
def matching_with_operators(args) | |
if (['AND', 'OR'] & args).any? | |
args.each_with_index.map do |arg, i| | |
if arg == 'AND' | |
contains?(args[i-1]) && contains?(args[i+1]) | |
elsif arg == 'OR' | |
contains?(args[i-1]) || contains?(args[i+1]) | |
end | |
end.compact.last | |
end | |
end | |
def matching_without_operators(args) | |
args.map { |arg| contains?(arg) }.last | |
end | |
def contains?(arg) | |
contains = array_or_string_content(arg).include?(filter_arg(arg)) | |
arg[0] == '-' ? !contains : contains | |
end | |
def array_or_string_content(arg) | |
if arg.include?('*') || arg.split.size > 1 | |
string_content | |
else | |
array_content | |
end | |
end | |
def filter_arg(arg) | |
arg.gsub(/-|\*|\"/, '') | |
end | |
def process_parentheses(str) | |
while str.include?('(') do | |
sub_query = str[str.index('(') + 1, str.index(')') - 1] | |
str.gsub!("(#{sub_query})", solve_sub_query(sub_query)) | |
end | |
str | |
end | |
def solve_sub_query(sub_query) | |
if matching_with_operators(tokenize(sub_query)) | |
array_content.first # existent word | |
else | |
"#SDX$#CVCDF@##GD123FGDG@#1231" #nonexistent word | |
end | |
end | |
def tokenize(str) | |
str.split(/\s(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/).select do |s| | |
s.present? | |
end.map do |s| | |
s.gsub(/(^ +)|( +$)|(^["']+)|(["']+$)/,'') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment