Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert string to conditional and statements

I have string variable like:

s = 'apple<3,meizu>5;samsung=9,foo=bar'

and a of dictionaries like:

 D = [  
        {'apple': 9, 'meizu': 12, 'samsung': 90, 'oppo': 12', foo': 'bar'}, 
        {'apple': 91, 'meizu': 22, 'samsung': 72, 'foo': 'test'},
         ...
     ]

I need to convert s to

"if apple < 3 and (meizu > 5 or samsung==9) and foo=='bar'"  # (semicolon is OR, comma is AND)

and check each element of list D with this conditional, like:

for i in D:
  if i['apple']<3 and (i['meizu']>5 or i['samsung']==9) and i['foo']=='bar':
     print ('ok')

I don't understand how to implement it. I tried eval(s), but I'm not sure that is a good solution.

like image 481
SmartSt Avatar asked Oct 17 '25 13:10

SmartSt


1 Answers

You could achieve this via a number of string replacements:

  • replace "=" with "==" (careful if you also have <= and >=)
  • replace name x with d['x']; you can use re.sub with a callback for this
  • replace , with and and ; with or

The tricky part is to make or bind stronger than and, but you can achieve this by introducing parentheses around all the and operators (as well as at the beginning and at the end of the string), but not around the or. (This might fail if the string already contains parens, but I'd assume that this is some sort of normalized form without parentheses.)

import re
def to_code(string):
    code = "(" + string + ")"
    code = re.sub("[a-z]+", lambda m: "d['%s']" % m.group(0), code)
    code = code.replace(",", ") and (")
    code = code.replace(";", " or ")
    code = code.replace("=", "==")
    return code

s = 'apple<3,meizu>5;samsung=9,foo=bar'
code = to_code(s)
# (d['apple']<3) and (d['meizu']>5 or d['samsung']==9) and (d['foo']==d['bar'])

Then, you can eval those strings with d being the different dictionaries.

D = [{'apple': 2, 'meizu': 12, 'samsung': 9, 'oppo': 12, 'foo': 42, 'bar': 42}, 
     {'apple': 91, 'meizu': 22, 'samsung': 72, 'foo': 'test', 'bar': "blub"}]

for d in D:
    print(eval(code)) # prints True, False
like image 62
tobias_k Avatar answered Oct 20 '25 06:10

tobias_k



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!