Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby - Find characters inside brackets

I am having a string in Ruby. I need to iterate through the brackets in the string.

My String:

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

First Iteration should return:

((MILK AND SOYA) OR NUT) AND COCONUT

Second Iteration should return the below:

(MILK AND SOYA) OR NUT

Third Iteration should return the following text:

MILK AND SOYA

How to do this in Ruby? Thanks in advance for the help.

like image 825
Suriya Prabha Avatar asked Aug 31 '25 17:08

Suriya Prabha


2 Answers

thy this solution:

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 string inside brackets

like image 154
Dmitry Cat Avatar answered Sep 02 '25 14:09

Dmitry Cat


gsub and regex

@DmitryCat's solution works fine with your example, but it seems you might be interested in the innermost brackets first.

So you'll need to make sure the characters between brackets aren't brackets :

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

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

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

it outputs :

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

Boolean logic to tree

With parser gem

Regexen probably aren't the right tool for this job.

This parser gem would have no problem analysing 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 : a Root node and children method. Which you can call recursively to get any information about your expression.

With sexp gem

(Thanks to @Casper for this suggestion)

It looks like sexp gem might also work, possibly with an easier 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 mentioned by @Casper in the comments (thanks again!), you're trying to reinvent the wheel. If you need full text search for Rails with boolean expressions, Sphinx is a great tool. It's fast, good, reliable and there's an adapter for Ruby/Rails : thinkingsphinx.

like image 28
Eric Duminil Avatar answered Sep 02 '25 14:09

Eric Duminil