You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将pyparsing解析的布尔表达式转换为Python可执行的集合运算逻辑?

实现方案

核心逻辑:你已经完成了表达式解析生成布尔树的步骤,只需要给AND_、OR_两个类实现两个核心能力即可满足需求:

  1. 实现__contains__魔术方法,直接支持value in 表达式的判断语法
  2. 实现eval方法,直接遍历子节点计算出整个表达式的结果集

代码实现

from typing import List, Dict, Set, Union

# 布尔表达式节点基类,存储全局数据
class BoolExpr:
    # 存储键对应的字符串集合,提前转集合提升查找效率
    data: Dict[str, Set[str]] = None
    
    @classmethod
    def set_data(cls, input_data: Dict[str, List[str]]):
        cls.data = {k: set(v) for k, v in input_data.items()}

# 交集节点类
class AND_(BoolExpr):
    def __init__(self, children: List[Union[str, BoolExpr]]):
        self.children = children
    
    def __contains__(self, value: str) -> bool:
        # 交集要求所有子条件都满足
        for child in self.children:
            if isinstance(child, str):
                if value not in self.data[child]:
                    return False
            else:
                if value not in child:
                    return False
        return True
    
    def eval(self) -> Set[str]:
        # 计算所有子节点的交集
        result = None
        for child in self.children:
            current = self.data[child] if isinstance(child, str) else child.eval()
            result = current.copy() if result is None else result & current
        return result

# 并集节点类
class OR_(BoolExpr):
    def __init__(self, children: List[Union[str, BoolExpr]]):
        self.children = children
    
    def __contains__(self, value: str) -> bool:
        # 并集要求任意一个子条件满足即可
        for child in self.children:
            if isinstance(child, str):
                if value in self.data[child]:
                    return True
            else:
                if value in child:
                    return True
        return False
    
    def eval(self) -> Set[str]:
        # 计算所有子节点的并集
        result = set()
        for child in self.children:
            current = self.data[child] if isinstance(child, str) else child.eval()
            result |= current
        return result

使用示例

# 加载你的测试数据
test_data = {'A': ['Hi', 'No', 'Yes'], 'B': ['Why', 'No', 'Okay'], 'C': ['Okay']}
BoolExpr.set_data(test_data)

# 你通过pyparsing解析生成的布尔树,对应表达式 (A and B) or C
parsed_expr = OR_([
    AND_(['A', 'B']),
    'C'
])

# 需求1:单个值判断,完全符合你要的 if value in expr 语法
print("No" in parsed_expr)  # 输出 True
print("Hi" in parsed_expr)  # 输出 False

# 手动遍历所有值收集结果的写法
all_values = set()
for lst in test_data.values():
    all_values.update(lst)
output = []
for val in all_values:
    if val in parsed_expr:
        output.append(val)
print(output)  # 输出 ['No', 'Okay'](集合顺序不固定,可自行排序)

# 需求2:直接获取整个表达式的结果,无需手动遍历
result = parsed_expr.eval()
print(list(result))  # 输出 ['No', 'Okay']

补充说明

  • 提前把列表转成集合是为了把in操作的时间复杂度从O(n)降到O(1),数据量大的时候性能提升明显
  • 你只需要给pyparsing的解析结果加一层递归转换逻辑,把解析到的节点转成对应AND_/OR_的实例即可,叶子节点直接存字典的键字符串
  • 如果后续需要支持not逻辑,新增一个NOT_类,实现对应取反的__contains__和eval方法即可

内容的提问来源于stack exchange,提问作者mimookies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 18:09:01