问题描述
我有像这样的字符串变量:
s = 'apple<3,meizu>5;samsung=9,foo=bar'
以及类似的字典:
D = [
{'apple': 9, 'meizu': 12, 'samsung': 90, 'oppo': 12', foo': 'bar'},
{'apple': 91, 'meizu': 22, 'samsung': 72, 'foo': 'test'},
...
]
我需要将s
转换为
"if apple < 3 and (meizu > 5 or samsung==9) and foo=='bar'" # (semicolon is OR, comma is AND)
并使用此条件检查列表D
每个元素,例如:
for i in D:
if i['apple']<3 and (i['meizu']>5 or i['samsung']==9) and i['foo']=='bar':
print ('ok')
我不知道如何实现它。
我尝试了eval(s)
,但是我不确定这是一个好的解决方案。
1楼
您可以通过许多字符串替换来实现:
-
将
"="
替换为"=="
(请注意,如果您同时具有<=
和>=
) -
将名称
x
替换为d['x']
; 您可以将与回调一起使用 -
取代
,
与and
和;
用or
棘手的部分是使or
绑定得比and
强,但您可以通过在所有and
运算符(以及字符串的开头和结尾)周围引入括号,而不是在or
周围引入括号来实现这一点。
(如果字符串已经包含括号,则可能会失败,但是我认为这是某种形式的无括号的规范化形式。)
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'])
然后,您可以使用d
作为不同的字典来eval
那些字符串。
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