我有一本以下形式的字典:
dict = {'a':25, 'ab':3.3, '(cd)': 4, 'ef':35, 'gh':12.2, etc.}
用户输入逗号分隔的短语(搜索字符串),例如:
'a > 5, 0 < (cd) < 6, ef < 35'
上面我们有三个条件,但它可以是任意数量的条件:我想要的是检查我的字典是否满足所有搜索条件。
if dict meets all conditions:
do somthing
else:
do something else
我可以获取搜索字符串,执行 split(','),循环每个条件,提取键、比较运算符 (< or >) 和数字,然后检查我的字典是否满足所有条件。在上面的例子中,满足 dict['a'] > 5,0 < dict['(cd)'] < 6 is also met, but dict['ef'] < 35 is not met.
有没有更快、更优雅的方法来做到这一点?从 'a > 5' 到 dict['a'] > 5 的更好更聪明的方法?例如,我可以将我的字典转换为 Pandas 数据框,并进行一些检查吗?除了我正在尝试的强力方法之外,Python 中是否还有评估方法或类似的方法?
为此构建一个解析器并不难。您可以使用
operator
包来处理条件,除此之外它只是一堆格式化和循环数据。
import operator, re
# regex to find operators
reop = re.compile(r'(?P<oper>(>=|<=|<|>|==))')
# dictionary of operators
oper = {'<' :operator.lt,
'>' :operator.gt,
'<=':operator.le,
'>=':operator.ge,
'==':operator.eq}
def check_conditions(data:dict, conditions:str) -> bool:
# stores condition results
facts = []
for cond in conditions.split(','):
# stores values and operators
v, o = [], []
# parse values and operators
for part in cond.strip().split(' '):
if part.isdigit():
v.append(int(part))
elif m := reop.match(part):
o.append(oper.get(m.group('oper')))
else:
v.append(data.get(part))
# make sure we have one more value than operators
if (len(v) - len(o)) != 1:
raise ValueError
# store all condition results
facts += [o[i](*v[i:i+2]) for i in range(len(o))]
return all(facts)
data = {'a':25, 'ab':3.3, '(cd)': 4, 'ef':35, 'gh':12.2}
conds = 'a > 5, 0 < (cd) < 6, ef < 36'
print(check_conditions(data, conds))