Christian Ackermann
Christian Ackermann

Reputation: 31

Slicing strings backwards by index

I have a string that looks like this:

((id = id_2) AND (condition1 = condition2))

What I want is to get the string that ends with the first ')' and backwards until the associated '('. Then I use that string and replace it with something else. This way I can repeat the operation until I get a string that has no '(' or ')'. So far, my code is something like this:

original_string = '((id = id_2) AND (condition1 = condition2))'
while ')' in original_string:
    needed_string = original_string[original_string.index(')'):original_string.index('('):-1][::-1]
    original_string.replace(needed_string, 'False')

That works and after the first iteration I get what I want:

needed_string = '(id = id_2)'
original_string = '(False AND (condition1 = condition2))'

But in the next iteration, I get:

needed_string = 'False AND (condition1 = condition2)'

What I want for the second iteration is:

needed_string = '(condition1 = condition2)'

So that after I use replace, original_string looks like this:

original_string = '(False AND False)'

This way, during the 3rd iteration:

needed_string = '(False and False)'

and after replacing,

original_string = 'False'

I am new to python so I'm not sure if this is OK or if there's a better way to be doing this, but it has to be done in a simple way (without using any 3rd party libraries) or tokenizing

Upvotes: 3

Views: 80

Answers (2)

Dmitry Ermolov
Dmitry Ermolov

Reputation: 2237

The problem with your approach is that you find first left parenthesis not the corresponding one to right parenthesis you found before.

To solve this problem you can use regular expression as Kupiakos suggested or you can try to use str.rfind method

  def replace_first_expression(string, replacement):
      close_parenthesis_pos = string.find(')')
      if close_parenthesis_pos == -1:
          return string
      open_parenthesis_pos = string.rfind('(', 0, close_parenthesis_pos)
      if open_parenthesis_pos == -1:
          return string
      return string[:open_parenthesis_pos] + replacement + string[close_parenthesis_pos + 1:]

Upvotes: 3

Alyssa Haroldsen
Alyssa Haroldsen

Reputation: 3731

You could use regular expressions to find and replace all of the needed values.

import re
def get_groups(expr, replace):
    pattern = re.compile(r'\([^()]*\)')
    while True:
        m = pattern.search(expr)
        if m is None:
            break
        expr = expr[:m.start()] + replace + expr[m.end():]
        yield (m.group(), expr)

and use this method as such:

>>> expr = '((id = id_2) AND (condition1 = condition2))'
>>> for needed_string, original_string in get_groups(expr, 'False'):
        print('needed string   =', repr(needed_string))
        print('original string =', repr(original_string))
        print()

needed string   = '(id = id_2)'
original string = '(False AND (condition1 = condition2))'

needed string   = '(condition1 = condition2)'
original string = '(False AND False)'

needed string   = '(False AND False)'
original string = 'False'

Upvotes: 3

Related Questions