【问题标题】:Manipulate Nested Boolean Query String in Python在 Python 中操作嵌套的布尔查询字符串
【发布时间】:2017-05-10 00:01:36
【问题描述】:

我有这样的字符串布尔查询

   queryString= """And(
                      OR(abc,xyz,wxy),
                      AND(AND(xyz,wxy),xzy),
                      XOR(x1,y1, AND(xy,zz))  
                      )"""

目前我很难修改上面的查询字符串,因为我想

  1. 在最后一个XOR 中添加另一个OR(x3,y3)
  2. 删除整个OR(abc,xyz,wxy)

具有所需的输出

   resultQueryString= """And(                        
                            AND(AND(xyz,wxy),xzy),
                            XOR(x1,y1, AND(xy,zz),OR(x3,y3))  
                            )"""

我认为我不能轻易做到这一点,除非我为每个不同的查询想出一个复杂的正则表达式。

我正在尝试编写一个 python 函数,它将上面的字符串布尔查询作为输入并输出树数据结构。

这样我就可以遍历树并评估或更改我想要更改的查询的任何部分。

在上面的例子中,如果我把它当作一棵树,我可以很容易地看到根是AND 并遍历/修改其他分支等等。

【问题讨论】:

    标签: python regex parsing nlp booleanquery


    【解决方案1】:

    ast.parse 函数似乎几乎完全符合您的要求:

    ast.dump(ast.parse("""And(                        
                            AND(AND(xyz,wxy),xzy),
                            XOR(x1,y1, AND(xy,zz),OR(x3,y3))  
                            )""").body[0].value)
    

    Call(func=Name(id='And', ctx=Load()), args=[Call(func=Name(id='AND', ctx=Load()), args=[Call(func=Name(id='AND', ctx=Load()), args=[Name(id='xyz', ctx=Load()), Name(id='wxy', ctx=Load())], keywords=[], starargs=None, kwargs=None), Name(id='xzy', ctx=Load())], keywords=[], starargs=None, kwargs=None), Call(func=Name(id='XOR', ctx=Load()), args=[Name(id='x1', ctx=Load()), Name(id='y1', ctx=Load()), Call(func=Name(id='AND', ctx=Load()), args=[Name(id='xy', ctx=Load()), Name(id='zz', ctx=Load())], keywords=[], starargs=None, kwargs=None), Call(func=Name(id='OR', ctx=Load()), args=[Name(id='x3', ctx=Load()), Name(id='y3', ctx=Load())], keywords=[], starargs=None, kwargs=None)], keywords=[], starargs=None, kwargs=None)], keywords=[], starargs=None, kwargs=None)

    .body[0].value 删除了两个毫无意义的抽象层,.dump 仅用于输出。

    下面是执行您请求的输出转换的代码:

    class Filterer(ast.NodeTransformer):
        def visit_Call(self, node):
                name=node.func.id
                if name == "OR" and len(node.args) == 3:
                        return None
                elif name == "XOR":
                        args = [ast.Name("x3",ast.Load()),
                                ast.Name("y3",ast.Load())]
                        func = ast.Name("OR",ast.Load())
                        node.args.append(ast.Call(func, args, [], None, None))
                return self.generic_visit(node)
    

    这是以您的格式打印结果的代码,但空格除外:(Python 在其ast 模块中没有内置函数):

    class Printer(ast.NodeVisitor):
        def visit_Call(self, node):
                self.visit(node.func)
                print("(",end="")
                comma = False
                for arg in node.args:
                        if comma:
                                print(",",end="")
                        comma=True
                        self.visit(arg)
                print(")",end="")
        def visit_Name(self, node):
                print(node.id,end="")
    

    因此,最终代码将是:

    Printer().visit(Filterer().visit(ast.parse(queryString)))

    【讨论】:

    • 谢谢,你能不能也写一下queryString的代码,然后打印所需的输出,如resultQueryString所示
    • @Watt 完成。 (而且打印有点复杂)
    猜你喜欢
    • 2011-02-19
    • 2017-08-31
    • 2018-04-28
    • 2013-10-23
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多