Python 解析逻辑表达式
我有一个任务,我必须根据用户指定的逻辑表达式过滤数据帧。现在,我看到了一个名为PyParser或LARK的模块,我想使用它,但我似乎不知道如何设置它们 我有几个操作符,如Python 解析逻辑表达式,python,string,parsing,boolean-logic,boolean-expression,Python,String,Parsing,Boolean Logic,Boolean Expression,我有一个任务,我必须根据用户指定的逻辑表达式过滤数据帧。现在,我看到了一个名为PyParser或LARK的模块,我想使用它,但我似乎不知道如何设置它们 我有几个操作符,如CONTAINS,EQUAL,FUZZY\u MATCH等。此外,我还想将一些表达式组合成更复杂的表达式 示例表达式: 列A包含[1,2,3]和(列B模糊匹配'bla'或列C等于45) 因此,我希望有一些结构化的Dict或List,按照如何执行它们的顺序列出操作的级别。因此,此示例表达式的预期结果如下所示: [['ColumnA
CONTAINS
,EQUAL
,FUZZY\u MATCH
等。此外,我还想将一些表达式组合成更复杂的表达式
示例表达式:
列A包含[1,2,3]和(列B模糊匹配'bla'或列C等于45)
因此,我希望有一些结构化的Dict或List,按照如何执行它们的顺序列出操作的级别。因此,此示例表达式的预期结果如下所示:
[['ColumnA', 'CONTAINS', '[1, 2, 3]'], 'AND', [['ColumnB', 'FUZZY_MATCH', 'bla'], OR, ['ColumnC', 'EQUAL', '45']]]
或以书面形式:
{
'EXPR1': {
'col': 'ColumnA',
'oper': 'CONTAINS',
'value': '[1, 2, 3]']
},
'OPERATOR': 'AND',
'EXPR2': {
'EXPR21': {
'col': 'ColumnB',
'oper': 'FUZZY_MATCH',
'value': 'bla'
},
'OPERATOR': OR,
'EXPR22': {
'col': 'ColumnC',
'oper': 'EQUAL',
'value': '45'
}
}
}
或者类似的。如果你有更好的方法来构建结果,我愿意听取建议。我对这一点很陌生,所以我相当肯定这一点可以改进。有趣的问题:)
似乎是该算法的一个相对简单的应用。我写了一些代码来解析表达式,比如
“((20-10)*(30-20)/10+10)*2”
重新导入
def标记化(str):
返回re.findall(“[+/*()-]”|\d+”,表达式)
def是_编号(str):
尝试:
智力(str)
返回真值
除值错误外:
返回错误
def peek(堆栈):
如果没有堆栈,则返回堆栈[-1]
def应用_运算符(运算符、值):
operator=operators.pop()
right=values.pop()
left=values.pop()
values.append(eval({0}{1}{2}).format(左,运算符,右)))
def优先级更高(op1、op2):
先例={“+”:0,“-”:0,“*”:1,“/”:1}
返回先例[op1]>先例[op2]
def求值(表达式):
标记=标记化(表达式)
值=[]
运算符=[]
对于令牌中的令牌:
如果是_编号(令牌):
values.append(int(令牌))
elif令牌==“(”:
operators.append(令牌)
elif标记==”):
top=peek(操作员)
而top不是None和top!="(":
应用_运算符(运算符、值)
top=peek(操作员)
operators.pop()#丢弃'('
其他:
#接线员
top=peek(操作员)
而top不是None和top!=”(“且优先级更高(top,标记):
应用_运算符(运算符、值)
top=peek(操作员)
operators.append(令牌)
虽然peek(操作员)不是无:
应用_运算符(运算符、值)
返回值[0]
def main():
表达式=“((20-10)*(30-20)/10+10)*2”
打印(计算(表达式))
如果名称=“\uuuuu main\uuuuuuuu”:
main()
我认为我们可以稍微修改代码,使其适用于您的案例:
tokenize()
中标记输入字符串的方式基本上,如果字符串
ColumnA包含[1,2,3]和(ColumnB FUZZY_MATCH'bla'或ColumnC EQUAL 45)
,我们需要一个标记列表:['ColumnA'、'CONTAINS'、'[1,2,3]、'AND'、'('、'ColumnB'、'FUZZY_MATCH'、'bla'、'或''ColumnC'、'EQUAL'、'45'、')]
这在很大程度上取决于输入字符串的复杂程度,并且需要一些字符串处理,但它相当简单,我将把这留给您
is_number()
函数,以检测诸如ColumnA
,[1,2,3]
等内容。基本上,除了谓词
之外的所有内容都包含
/模糊匹配
/相等
、运算符和
/或
以及偏执词(
/)
op1
在['CONTAINS'、'EQUAL'、…]
和op2
是['and'、'OR']之间,则修改更高的优先级(op1、op2)
以返回true
这是因为我们希望
包含
和等于
总是在和
/或
之前进行计算apply_运算符(运算符,值)
以实现如何计算布尔表达式ColumnA包含[1,2,3]
或表达式true和false的逻辑
请记住,包含
/模糊匹配
/相等
/和
/或
等都是这里的运算符。
可能你需要在这里写很多if-else的例子,因为这里可能有很多不同的操作符
好的,谢谢你冗长完整的回答:)看起来这就是我要找的。我会在接下来的几天里测试它。当然。别忘了接受答案,如果它有效的话就结束这个问题;)我知道你已经得到了答案,但是如果你对使用Lark的解决方案感兴趣,请告诉我。