Python 在pyparsing中,如何格式化嵌套字典输出?

Python 在pyparsing中,如何格式化嵌套字典输出?,python,pyparsing,Python,Pyparsing,我正在使用pyparsing来解析以下输入: %FSLAX45Y67*% 我想要的输出格式是字典形式的: { 'notation': 'absolute', 'zeros': 'leading', 'x': { 'integer': 4, 'decimal': 5 }, 'y': { 'integer': 6, 'decimal': 7, }, 'gerber-command': 'FS' } 我目前得到的输出是: {

我正在使用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)

(省略了一些无关紧要的定义)。有什么建议吗?

您必须自由地使用
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)

您必须自由地使用
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)

有趣的是,为什么难题总是以递归结束

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',
}
请注意,根据您对问题的描述,我不确定您是否希望在dict的最后一个元素中使用“.”

尝试更深入:

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',
}

有趣的是,为什么难题总是以递归结束

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',
}
请注意,根据您对问题的描述,我不确定您是否希望在dict的最后一个元素中使用“.”

尝试更深入:

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',
}

使用pyparsing Group向返回的令牌添加结构。这可能会起到作用:

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']]
以下是添加结果名称后的效果:

preface = aword("As") + bword("Bs")
body = cword
ending = aword("As") + bword("Bs")

totalExpr = Group(preface)("preface") + body("body") + Group(ending)("ending")
print totalExpr.parseString("AA BB CCC A B").dump()
给出:

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

因为前言和结尾是分组的,所以它们的重复名称“As”和“Bs”是分开的。

使用pyparsing Group为返回的标记添加结构。这可能会起到作用:

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']]
以下是添加结果名称后的效果:

preface = aword("As") + bword("Bs")
body = cword
ending = aword("As") + bword("Bs")

totalExpr = Group(preface)("preface") + body("body") + Group(ending)("ending")
print totalExpr.parseString("AA BB CCC A B").dump()
给出:

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

因为前言和结尾是分组的,所以它们的重复名称“As”和“Bs”是分开的。

这不是关于输出的实际打印格式,而是关于pyparsing如何从一行代码块捕获和组织难以读取的数据类型。您可能需要添加一些错误检查。这不是关于输出的实际打印格式,而是pyparsing如何从一行代码块捕获和组织难以读取的数据类型。您可能需要添加一些错误检查。谢谢,但正如我在另一篇评论中提到的,我的问题是如何让pyparsing正确排列数据,而不是如何美化输出。(我修改了问题以反映这一点。)哦,我不知道你这次到底想要什么。希望你的问题能很快得到解决:-)好的努力。另外,请查看Python std库中的pprint模块。当dump()不是我想要的时,我经常使用pprint.pprint(parsedData.asList())打印一个缩进良好的解析标记列表。谢谢,但正如我在另一篇评论中提到的,我的问题是让pyparsing正确排列数据,而不是如何美化输出。(我修改了问题以反映这一点。)哦,我不知道你这次到底想要什么。希望你的问题能很快得到解决:-)好的努力。另外,请查看Python std库中的pprint模块。当dump()不是我想要的时,我经常使用pprint.pprint(parsedData.asList())打印一个缩进很好的解析标记列表。你的第一个建议让我更接近,但仍然有一些“剩余”:{'y':([4,3],{'integer':[(4,0)],'decimal':[(3,1)],'x':([6,5],{'integer':[(6,0)],'decimal:[(5,1)]),'zeros':'leading','notation':'absolute','gerber command':'FS'}您看到的'residence'只是嵌套ParseResults的repr输出。尝试使用您定义的名称访问结果:result.notation、result.x.integer、result.y.integer、result.x.decimal等。result.dump()看起来像什么?result.dump()看起来不错。我想我希望.asDict()的输出看起来像一本字典,但我想情况并非如此,这很好。@saardrimer-它可能看起来不像dict,但您仍然可以像dict一样使用它:
result['preference']['As']
->
“AA”
result.keys()
将给出
你的第一个建议让我更接近,但仍然有一些“余数”:{'y':([4,3],{'integer':[(4,0)],'decimal':[(3,1)],'x':([6,5],{'integer':[(6,0)],'decimal':[(5,1)]),'zeros':'leading','notation':'absolute','gerber command':'FS'}您看到的'residence'只是嵌套ParseResults的repr输出。请尝试使用您定义的名称访问结果:result.notation、result.x.integer、result.y.integer、result.x.decimal等。result.dump()看起来像什么看起来不错。我想我希望.asDict()输出看起来像一本字典,但我想情况并非如此,这完全是f