python - 从字符串中读取方程并解析它
问题描述
我有像这样以字符串形式编写的布尔数学表达式
"A and B or C and not D"
"A and (B or C) and not D"
我想用python解决它,“and”、“or”和“and not”和“or not”运算符将调用不同的函数。我想不出任何可以解决这个问题的想法。
我可以用 split 打破等式,但下一步是什么?
更新: A 和 B 和 other 可以包含一些单词,这些单词将返回一个列表,并在该列表上执行“and”、“or”和其他操作。
我已经创建了该列表,我可以解决 2 变量问题,但是当它有多个组合时如何解决它。
解决方案
符号包Sympy似乎是一个不错的选择。
在其基本形式中,sympy 需要,and
和or
,和,可以在调用解析器之前被替换。请注意,如果“Brandon”之类的名称包含“and”,则简单的字符串替换将无法正常工作。not
&
|
~
之后,您可以使用 sympy 进行任何类型的简化、操作和替换,就像任何其他数学表达式一样。
一个例子:
from sympy.parsing.sympy_parser import parse_expr
str = "Alice and (Bob or Carla) and not David"
str = str.replace('and', '&').replace('or', '|').replace('not', '~')
expr = parse_expr(str)
print(expr)
print(expr.subs({'Alice': True, 'Bob': False}))
输出:
Alice & ~David & (Bob | Carla)
Carla & ~David
在评论中,您要求对集合而不是布尔值进行操作。小数集在 Sympy 中表示为FiniteSet
. 通常,它们需要使用函数符号来编写:Union(arg1, arg2, arg3, ...)
. 但是我们可以使用布尔运算符And
,Or
它Not
确实允许中缀表示法构造一个表达式,然后像设置操作一样进行评估。
from sympy.parsing.sympy_parser import parse_expr
from sympy import Atom, FiniteSet, And, Or, Not, Union, Intersection, Complement
def evaluate_expr(expr, replacements, complete_set):
if isinstance(expr, Atom):
return expr.subs(replacements)
elif expr.func == Or:
return Union(*[evaluate_expr(a, replacements, complete_set) for a in expr.args])
elif expr.func == And:
return Intersection(*[evaluate_expr(a, replacements, complete_set) for a in expr.args])
elif expr.func == Not:
return Complement(complete_set, evaluate_expr(expr.args[0], replacements, complete_set))
replacements = {'Alice': {1, 2}, 'Bob': {1, 2, 3}, 'Carla': {5}, 'David': {1, 4, 6}}
for r in replacements:
# convert the replacements to their Sympy representation
replacements[r] = FiniteSet(*replacements[r])
print("Replacements:", replacements)
complete_set = Union(*replacements.values()) # the set of all possible values is used to implement "not"
tests = ["Alice", "Alice or Bob", "Alice and Bob and Carla", "Alice and (Bob or Carla) and not David"]
for test in tests:
expr = parse_expr(test.replace('and', '&').replace('or', '|').replace('not', '~'))
print(expr)
print(" --->", evaluate_expr(expr, replacements, complete_set))
输出:
Replacements: {'Alice': FiniteSet(1, 2), 'Bob': FiniteSet(1, 2, 3), 'Carla': FiniteSet(5), 'David': FiniteSet(1, 4, 6)}
Alice
---> FiniteSet(1, 2)
Alice | Bob
---> FiniteSet(1, 2, 3)
Alice & Bob & Carla
---> EmptySet
Alice & ~David & (Bob | Carla)
---> FiniteSet(2)
推荐阅读
- c++ - 我无法通过 vcpkg 导入 range-v3 库
- python - PYTHON - 合并日期索引上的两个数据框
- python - 如何每次运行脚本,同时访问 Flask 页面
- ios - 应用程序获得批准并准备销售后,iOS 应用程序内购买无法正常工作
- flutter - 如何使用颤振以编程方式发送推送通知?
- xamarin - UWP 上的 Xamarin.Auth 失败
- laravel - 如何在 laravel 中的数据表搜索框类型上调用 ajax
- c# - 为什么可选加载项未在功能区上显示为单独的选项卡?
- excel - 从条形图中删除#NV 标签
- java - EntityManager 在 Junit 测试中给出 NullPointerException