gpt4 book ai didi

python - 解析逻辑表达式

转载 作者:行者123 更新时间:2023-12-04 04:02:22 25 4
gpt4 key购买 nike

我有一项任务,我必须根据用户指定的逻辑表达式过滤 Pandas DataFrame。现在,我看到了一个名为 PyParser 或 LARK 的模块,我想使用它们,但我似乎无法弄清楚如何设置它们。

我有几个运算符,如 CONTAINSEQUALFUZZY_MATCH 等。另外,我想将一些表达式组合成更复杂的表达式.

示例表达式:

ColumnA CONTAINS [1, 2, 3] AND (ColumnB FUZZY_MATCH 'bla' OR ColumnC EQUAL 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'
}
}
}

或者类似的东西。如果您有更好的方法来构建结果,我愿意接受建议。我对此很陌生,所以我很确定这可以改进。

最佳答案

有趣的问题:)

似乎是 shunting yard 的一个相对简单的应用算法。
我编写了代码来解析像 "((20 - 10 ) * (30 - 20)/10 + 10 ) * 2" 这样的表达式 here .

import re


def tokenize(str):
return re.findall("[+/*()-]|\d+", expression)

def is_number(str):
try:
int(str)
return True
except ValueError:
return False


def peek(stack):
return stack[-1] if stack else None


def apply_operator(operators, values):
operator = operators.pop()
right = values.pop()
left = values.pop()
values.append(eval("{0}{1}{2}".format(left, operator, right)))


def greater_precedence(op1, op2):
precedences = {"+": 0, "-": 0, "*": 1, "/": 1}
return precedences[op1] > precedences[op2]


def evaluate(expression):
tokens = tokenize(expression)
values = []
operators = []
for token in tokens:
if is_number(token):
values.append(int(token))
elif token == "(":
operators.append(token)
elif token == ")":
top = peek(operators)
while top is not None and top != "(":
apply_operator(operators, values)
top = peek(operators)
operators.pop() # Discard the '('
else:
# Operator
top = peek(operators)
while top is not None and top != "(" and greater_precedence(top, token):
apply_operator(operators, values)
top = peek(operators)
operators.append(token)
while peek(operators) is not None:
apply_operator(operators, values)

return values[0]


def main():
expression = "((20 - 10 ) * (30 - 20) / 10 + 10 ) * 2"
print(evaluate(expression))


if __name__ == "__main__":
main()

我认为我们可以稍微修改代码以使其适用于您的情况:

  1. 我们需要修改在 tokenize() 中标记化输入字符串的方式。
    基本上,给定字符串 ColumnA CONTAINS [1, 2, 3] AND (ColumnB FUZZY_MATCH 'bla' OR ColumnC EQUAL 45),我们需要一个标记列表:
    ['ColumnA', 'CONTAINS', '[1, 2, 3]', 'AND', '(', 'ColumnB', 'FUZZY_MATCH', "'bla'", 'OR', 'ColumnC ', 'EQUAL', '45', ')'].
    这在很大程度上取决于输入字符串的复杂程度,并且需要进行一些字符串处理,但它相当简单,我会把它留给你。
  2. 修改 is_number() 函数以检测 ColumnA[1, 2, 3]
    基本上,除了谓词 CONTAINS/FUZZY_MATCH/EQUAL、运算符 AND/OR 和括号 (/)
  3. 修改 greater_precedence(op1, op2) 以在 op1 位于 ['CONTAINS', 'EQUAL', ..]op2['AND', 'OR']
    这是因为我们希望始终在 AND/OR 之前评估 containsequals
  4. 修改 apply_operator(operators, values) 以实现如何计算 bool 表达式 ColumnA CONTAINS [1, 2, 3] 或表达式 true 的逻辑AND false.
    请记住 CONTAINS/FUZZY_MATCH/EQUAL/AND/OR 等都是运算符在这里。
    您可能需要在此处编写很多 if-else 情况,因为可能有很多不同的运算符。

关于python - 解析逻辑表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62893234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com