2017-05-10 2 views
0

にネストされたブールクエリ文字列を操作し、私は、現在ではこのPythonの

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

のような文字列のブールクエリを持って、私は上記のクエリ文字列を変更するために、私は別のものを追加

  1. にしたいと、それは、難しいです最後XOR
  2. OR(x3,y3)OR(abc,xyz,wxy)
全体を削除します所望の出力

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

と10

は、私はそれぞれ別のクエリのための洗練された正規表現を思い付くしない限り、私は簡単にそれをしないことができると思います。

私は上記の文字列ブールクエリを入力として受け取り、ツリーデータ構造を出力するPython関数を記述しようとしています。

私はツリーをトラバースして、変更するクエリのどの部分を評価したり変更することができるようにします。

上記の例では、ツリーとして持っていれば、ルートがANDであることが簡単にわかり、他のブランチをトラバース/変更することができます。

答えて

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は、次の2つの抽象無意味な層を除去し、そして.dumpはちょうど出力のためです。

ここで、あなたが要求した変換を行うコードはありますか? n個の出力:

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)))

+0

おかげで、あなたは喜ばも '' 'queryString'''を取り、その後、所望の出力を出力するコードを書くことができます'' 'resultQueryString''' – Watt

+0

@WattDoneと表示されています。 (そしてやや複雑な印刷) – ppperry