Ruby - finding characters within parentheses

I have a string in Ruby. I need to iterate through the parentheses in a string.

My line:

(((MILK AND SOYA) OR NUT) AND COCONUT)

      

The first iteration should return:

((MILK AND SOYA) OR NUT) AND COCONUT

      

The second iteration should go back below:

(MILK AND SOYA) OR NUT

      

The third iteration should return the following text:

MILK AND SOYA

      

How do I do this in Ruby? Thanks in advance for your help.

+3


source to share


3 answers


Your choice:

str = "(((MILK AND SOYA) OR NUT) AND COCONUT)"
while not str.nil?
    puts str = str.match(/\((.*)\)/).to_a.last
end # => 
((MILK AND SOYA) OR NUT) AND COCONUT
(MILK AND SOYA) OR NUT
MILK AND SOYA

      



regex /\((.*)\)/

searches for a string inside parentheses

+4


source


gsub and regex

@DmitryCat's solution works great with your example, but it looks like you're interested in the innermost brackets first.

Therefore, you need to make sure that the characters between the parentheses are not parentheses:

str = "(((MILK AND SOYA) OR NUT) AND COCONUT)"

while str.gsub!(/\(([^\(\)]+)\)/){ p $1; ''}
end
# "MILK AND SOYA"
# " OR NUT"
# " AND COCONUT"

      

FROM "((MILK AND SOYA) OR (MILK AND NUT))"

output:

# "MILK AND SOYA"
# "MILK AND NUT"
# " OR "

      

Logic logic for a tree

With parser graph

Regexen is probably not the right fit for the job.



This parser

gem
will have no problem parsing your expression:

require 'parser/current'

str = "(((MILK AND SOYA) OR NUT) AND COCONUT)"

p Parser::CurrentRuby.parse(str.gsub(/\b(and|or)\b/i){|s| s.downcase})

# s(:begin,
#   s(:and,
#     s(:begin,
#       s(:or,
#         s(:begin,
#           s(:and,
#             s(:const, nil, :MILK),
#             s(:const, nil, :SOYA))),
#         s(:const, nil, :NUT))),
#     s(:const, nil, :COCONUT)))

      

You now have a tree: Root node method and children

. Which can be called recursively to get information about your expression.

With a gem sexp

(Thanks @Casper for this suggestion)

It looks like the sexp

gem
can work as well, perhaps with a lighter syntax than parser

:

require 'sxp'
p SXP.read("(((MILK AND SOYA) OR (NUT AND SOYA)) AND COCONUT)")
# [[[:MILK, :AND, :SOYA], :OR, [:NUT, :AND, :SOYA]], :AND, :COCONUT]

      

Sphinx

As @Casper mentioned in the comments (thanks again!), You are trying to reinvent the wheel. If you need Rails full text search with booleans, Sphinx is a great tool. It's fast, good, reliable, and there is an adapter for Ruby / Rails: thinkingsphinx .

+3


source


Use index to get the first character '(' and rindex to find the close character ')':

s = "(((MILK AND SOYA) OR NUT) AND COCONUT)"
s = s.slice(s.index('(') + 1, s.rindex(')') - 1) unless s.index('(').nil? || s.rindex(')').nil?

      

With this code you will get all the required string. Just call it in a loop until s is

I hope this helps

0


source







All Articles