2013-10-13 77 views
1

我使用pyparsing來解析下輸入:在pyparsing中,如何格式化嵌套的字典輸出?

%FSLAX45Y67*% 

輸出格式我之後,在字典的形式,就是:

{ 
    'notation': 'absolute', 
    'zeros': 'leading', 
    'x': { 
    'integer': 4, 
    'decimal': 5 
    }, 
    'y': { 
    'integer': 6, 
    'decimal': 7, 
    }, 
    'gerber-command': 'FS' 
} 

目前我得到的輸出是:

{ 
    'notation': 'absolute', 
    'decimal': 6, 
    'zeros': 'leading', 
    'integer': 6, 
    'y': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}), 
    'x': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}), 
    'gerber-command': 'FS' 
} 

(請注意,我的問題不是如何使輸出看起來正確,而是如何讓pyparsing安排我想要的數據。)

用下面的代碼:

single_digit = pyp.Regex(r'(\d)').setParseAction(lambda t: int(t[0])) 

cmd_format = pyp.Literal('FS') 
cmd_format_opt_leading_zeros = pyp.Literal('L').setParseAction(pyp.replaceWith('leading')) 
cmd_format_opt_trailing_zeros = pyp.Literal('T').setParseAction(pyp.replaceWith('trailing')) 

format_zeros = ((cmd_format_opt_leading_zeros('zeros')) | 
       (cmd_format_opt_trailing_zeros('zeros'))) 

format_notation = ((cmd_format_opt_absolute('notation')) | 
        (cmd_format_opt_incremental('notation'))) 

format_data = (single_digit)('integer') + single_digit('decimal') 

gformat = (inst_del + 
      cmd_format('gerber-command') + 
      format_zeros + 
      format_notation + 
      'X' + (format_data)('x') + 
      'Y' + (format_data)('y') + 
      inst_end + 
      inst_del) 

(一些瑣碎的定義中省略)。有什麼建議麼?

回答

2

使用pyparsing集團結構添加到返回的標記。這可能會做的工作:

gformat = (inst_del + 
      cmd_format('gerber-command') + 
      format_zeros + 
      format_notation + 
      'X' + pyp.Group(format_data)('x') + 
      'Y' + pyp.Group(format_data)('y') + 
      inst_end + 
      inst_del) 

Pyparsing的默認行爲是隻返回令牌的平面列表,以免正是基於以什麼順序添加什麼樣的條件,在結構猜測。舉例來說,如果你有這樣的:

aword = Word("A") 
bword = Word("B") 
cword = Word("C") 

preface = aword + bword 
body = cword 
ending = aword + bword 

totalExpr = preface + body + ending 

print totalExpr.parseString("AA BB CCC A B").asList() 

pyparsing將只返回列表

['AA', 'BB', 'CCC', 'A', 'B'] 

如果要應用結構(這是保持嵌套結果名字從踩到對方尤爲重要,因爲你是在整數和小數)的重疊看到,使用組:

totalExpr = Group(preface) + body + Group(ending) 

這給:

[['AA', 'BB'], 'CCC', ['A', 'B']] 

這裏是如何做到這一點看,如果你添加的結果名稱:

給出:

[['AA', 'BB'], 'CCC', ['A', 'B']] 
- body: CCC 
- ending: ['A', 'B'] 
    - As: A 
    - Bs: B 
- preface: ['AA', 'BB'] 
    - As: AA 
    - Bs: BB 

由於序言和結尾的分組,他們的重名「作爲」和「BS」保持分開。

+0

你的第一個建議讓我更接近,但仍有一些「殘留」:{'y':([4,3],{'integer':[(4,0)],'decimal':[(3,1 )]),'x':([6,5],{'integer':[(6,0)],'decimal':[(5,1)]}),'zeros':'leading' ,'notation':'絕對','gerber-command':'FS'} –

+0

您看到的'殘留'只是嵌套的ParseResults的repr輸出。嘗試使用已定義的名稱訪問結果:result.notation,result.x.integer,result.y.integer,result.x.decimal等。result.dump()的外觀如何? – PaulMcG

+0

result.dump()看起來不錯。我想我期望.asDict()輸出看起來完全像一本字典,我想不是這種情況,這非常好。 –

1

您必須寬鬆地使用setParseAction來刪除不需要的信息。 在format_data你需要一個函數,該函數將single_digit的輸出轉換成你想要的格式。

def _format_data(x): 
    return {"integer": x["integer"][0][0], 
      "decimal": x["decimal"][0][0]} 

format_data.setParseAction(_format_data) 
+0

這不是關於輸出的實際打印格式,而是pyparsing如何捕獲和組織數據 –

+0

很難從一行代碼塊中讀取。您可能必須添加一些錯誤檢查。 – ebo

1

有趣的是,爲什麼難題始終以遞歸結束?

x=\ 
{ 
    'notation': 'absolute', 
    'zeros': 'leading', 
    'x': { 
    'integer': 4, 
    'decimal': 5 
    }, 
    'y': { 
    'integer': 6, 
    'decimal': 7, 
    }, 
    'gerber-command': 'FS' 
} 

def superPrint(inidic={},indent=' '): 
    for k,v in inidic.items(): 
     if isinstance(v,dict): 
      yield "\n%s'%s': {"%(indent,k) 
      for i in superPrint(v,indent+' '*(len(k)+1)): 
       yield i 
      yield "\n%s},"%indent 
     else: 
      yield "\n%s'%s': '%s',"%(indent,k,v) 

print '{%s\n}'%''.join(superPrint(x)) 

結果:

{ 
    'y': { 
    'integer': '6', 
    'decimal': '7', 
    }, 
    'x': { 
    'integer': '4', 
    'decimal': '5', 
    }, 
    'zeros': 'leading', 
    'notation': 'absolute', 
    'gerber-command': 'FS', 
} 

注意,根據您的quesion的描述,我不知道你是否希望了「」在字典中的最後一個元素。

嘗試更深:

x=\ 
{ 
    'notation': 'absolute', 
    'zeros': 'leading', 
    'x': { 
    'integer': 4, 
    'decimal': 5 
    }, 
    'y': { 
    'integer': 6, 
    'decimal': {'try':7, 
       'tryHarder':{'wow':8, 
          'seemsGood':{'wooow':9}}}, 
    }, 
    'gerber-command': 'FS' 
} 

print '{%s\n}'%''.join(superPrint(x)) 

似乎不錯:

{ 
    'y': { 
    'integer': '6', 
    'decimal': { 
      'try': '7', 
      'tryHarder': { 
         'wow': '8', 
         'seemsGood': { 
           'wooow': '9', 
         }, 
      }, 
    }, 
    }, 
    'x': { 
    'integer': '4', 
    'decimal': '5', 
    }, 
    'zeros': 'leading', 
    'notation': 'absolute', 
    'gerber-command': 'FS', 
} 
+0

謝謝,但正如我在另一條評論中提到的,我的問題是關於如何使用pyparsing來正確排列數據,而不是如何對輸出進行優化。 (我已經修改了這個問題來反映這一點。) –

+0

哦,我不知道這次你到底想要什麼。希望你的問題很快就會得到解決:-) – tcpiper

+0

好的努力。另外,請查看Python std lib中的pprint模塊。當我不需要dump()時,我經常使用pprint.pprint(parsedData.asList())打印一個很好地縮進的解析標記列表。 – PaulMcG