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.
You could achieve this via a number of string replacements:
"="
with "=="
(careful if you also have <=
and >=
)x
with d['x']
; you can use re.sub
with a callback for this,
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With