2016-10-04 2 views
0

入れ子リストを辞書に変換するクラスを作成しました。再帰的に辞書を変更する

['function:and', 
    ['variable:X', 'function:>=', 'value:13'], 
    ['variable:Y', 'function:==', 'variable:W']] 

、出力は次の形式で辞書でなければなりません:以下は私の入力である

{ 
    "function": "and", 
    "args": [ 
    { 
     "function": ">=", 
     "args": [ 
     { 
      "variable": "X" 
     }, 
     { 
      "value": 13 
     } 
     ] 
    }, 
    { 
     "function": "==", 
     "args": [ 
     { 
      "variable": "Y" 
     }, 
     { 
      "variable": "W" 
     } 
     ] 
    } 
    ] 
} 

これは、入力リストを受け取り、クラスであり、必要な辞書を返す必要があります。

class Tokenizer(object): 
    def __init__(self, tree): 
     self.tree = tree 
     self.filter = {} 

    def to_dict(self, triple): 
     my_dict = {} 
     try: 
      first = triple[0] 
      second = triple[1] 
      third = triple[2] 
     except KeyError: 
      return 
     if type(second) == str and type(third) == str: 
      my_dict['function'] = second.split(':')[-1] 
      my_dict['args'] = [ 
       {first.split(':')[0]: first.split(':')[1]}, 
       {third.split(':')[0]: third.split(':')[1]}] 
     # case recursive 
     if type(second) == list: 
      my_dict['function'] = first.split(':')[-1] 
      my_dict['args'] = [second, third] 
     return my_dict 

    def walk(self, args): 
     left = self.to_dict(args[0]) 
     right = self.to_dict(args[1]) 
     if isinstance(left, dict): 
      if 'args' in left.keys(): 
       left = self.walk(left['args']) 
     if isinstance(right, dict): 
      if 'args' in right.keys(): 
       right = self.walk(right['args']) 
     args = [left, right] 
     return args 

    def run(self): 
     self.filter.update(self.to_dict(self.tree)) 
     if 'args' in self.filter.keys(): 
      self.filter['args'] = self.walk(self.filter['args']) 


tree = [ 
    'function:and', 
     ['variable:X', 'function:>=', 'value:13'], 
     ['variable:Y', 'function:==', 'variable:W'] 
    ] 

import pprint 
pp = pprint.PrettyPrinter(indent=4) 
t = Tokenizer(tree) 
t.run() 
pp.pprint(t.filter) 

私の再帰的な方法walkは、それがどうあるべきかやっていないと私は私が間違ってやっていることは理解できないので、私は、再帰の総吸盤です。

私は取得しています出力は次のようになります。あなたがすべてで再帰に行く必要はありません、あなたの特定のテストケースについては

{ 'args': [[None, None], [None, None]], 'function': 'and'} 
+0

_私のメソッドはそれがすべきことをしていません_それは何をしていますか? –

+0

@ジョンゴードン:出力を追加するように編集しました、ありがとう! – PepperoniPizza

+0

https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ –

答えて

1

。電話番号をコメントにすることができます。

def walk(self, args): 
    left = self.to_dict(args[0]) 
    right = self.to_dict(args[1]) 
    #if isinstance(left, dict): 
    # if 'args' in left.keys(): 
    #  left = self.walk(left['args']) 
    #if isinstance(right, dict): 
    # if 'args' in right.keys(): 
    #  right = self.walk(right['args']) 
    args = [left, right] 
    return args 

となります。 あなただけがあなたの入力中にネストされた関数を可能とするならば再帰に移動する必要があります:

['function:and', 
     ['variable:X', 'function:>=', 'value:13'], 
     ['function:==', 
      ['variable:R', 'function:>=', 'value:1'], 
      ['variable:Z', 'function:==', 'variable:K'] 
     ] 
] 

、あなたは基本ケースをチェックしなければならないので、あなたがあなたのargsキーの値は、未処理の値が含まれている場合にのみ再帰に入ります:

def walk(self, args): 
    left = self.to_dict(args[0]) 
    right = self.to_dict(args[1]) 
    if isinstance(left, dict): 
     if 'args' in left.keys() and isinstance(left['args'][0], list): 
      left = self.walk(left['args']) 
    if isinstance(right, dict): 
     if 'args' in right.keys() and isinstance(right['args'][0], list): 
      right = self.walk(right['args']) 
    args = [left, right] 
    return args 

、その後、あなたはこれを取得します:

ご入力リストが規則的な構造だった場合、それは容易になるだろう。また
{ 'args': [ { 'args': [{ 'variable': 'X'}, { 'value': '13'}], 
       'function': '>='}, 
      { 'args': [ { 'args': [ { 'variable': 'R'}, 
              { 'value': '1'}], 
           'function': '>='}, 
          { 'args': [ { 'variable': 'Z'}, 
              { 'variable': 'K'}], 
           'function': '=='}], 
       'function': '=='}], 
'function': 'and'} 

一貫して関数名フィールドに続く引数フィールドを持っていました。その後、to_dictメソッドを大幅に簡略化できます。

関連する問題