2013-10-13 42 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