我有一个人为问题的实例:

import pyparsing as pp

fname = pp.OneOrMore( pp.Word("Max") ).setResultsName("fname")
mname = pp.OneOrMore(s pp.Word("Joseph") ).setResultsName("mname")
lname = pp.OneOrMore( pp.Word("Andrews") ).setResultsName("lname")
another_mname = pp.OneOrMore(pp.Word("Miller")).setResultsName("mname")

full = fname + mname + lname + another_mname

output = full.parseString("Max Joseph Joseph Andrews Miller Miller").asDict()

# current output
{'fname': ['Max'], 'lname': ['Andrews'], 'mname': ['Miller', 'Miller']}


很明显,为什么输出是这样。但是,我也想收集“约瑟夫”作为另一个价值。例如

# desired output
{'fname': ['Max'], 'lname': ['Andrews'], 'mname': ['Joseph', 'Joseph', 'Miller', 'Miller']}


谢谢。

最佳答案

您的代码无效,因为您将结果的名称设置为相同。
这导致在结果"mname"中与mname关联的dict()条目被与"mname"关联的another_mname条目替换。

解决此问题的一种方法是将名称收集到两个单独的结果中,然后将它们加入:

import pyparsing as pp

fname = pp.OneOrMore(pp.Word("Max"))("fname")
mname = pp.OneOrMore(pp.Word("Joseph"))("mname")
lname = pp.OneOrMore(pp.Word("Andrews"))("lname")
another_mname = pp.OneOrMore(pp.Word("Miller"))("mname2")

full = fname + mname + lname + another_mname

output = full.parseString("Max Joseph Joseph Andrews Miller Miller").asDict()
print(output)
# {'fname': ['Max'], 'mname': ['Joseph', 'Joseph'], 'lname': ['Andrews'], 'mname2': ['Miller', 'Miller']}

# clean-up dict
output['mname'] = output['mname'] + output['mname2']
del output['mname2']

print(output)
# {'fname': ['Max'], 'mname': ['Joseph', 'Joseph', 'Miller', 'Miller'], 'lname': ['Andrews']}




请注意,您不能简单地将mname定义为:

mname = pp.OneOrMore(pp.Word("Joseph") | pp.Word("Miller"))("mname")


这将导致类似的问题:

import pyparsing as pp

fname = pp.OneOrMore(pp.Word("Max"))("fname")
mname = pp.OneOrMore(pp.Word("Joseph") | pp.Word("Miller"))("mname")
lname = pp.OneOrMore(pp.Word("Andrews"))("lname")

full = fname + mname + lname + mname

output = full.parseString("Max Joseph Joseph Andrews Miller Miller").asDict()
print(output)
# {'fname': ['Max'], 'mname': ['Miller', 'Miller'], 'lname': ['Andrews']}


但由于另一个原因:mname末尾的full替换了mname的先前值。



也可以自动执行此操作,例如

import pyparsing as pp

fname = pp.OneOrMore(pp.Word("Max"))("fname")
mname = pp.OneOrMore(pp.Word("Joseph"))("mname:0")
lname = pp.OneOrMore(pp.Word("Andrews"))("lname")
another_mname = pp.OneOrMore(pp.Word("Miller"))("mname:1")

full = fname + mname + lname + another_mname

output = full.parseString("Max Max Joseph Joseph Andrews Miller Miller").asDict()
print(output)
# {'fname': ['Max', 'Max'], 'mname:0': ['Joseph', 'Joseph'], 'lname': ['Andrews'], 'mname:1': ['Miller', 'Miller']}


def quench(pp_dict, mapping=lambda k: k.split(':')[0]):
    result = {}
    to_remove = []
    for k, v in pp_dict.items():
        new_k = mapping(k)
        if k != new_k:
            if new_k not in result:
                result[new_k] = []
            result[new_k].extend(v)
        else:
            result[k] = v
    return result


print(quench(output))
# {'fname': ['Max', 'Max'], 'mname': ['Joseph', 'Joseph', 'Miller', 'Miller'], 'lname': ['Andrews']}


或者,通过自动将多个full实例转换为编号实例(例如"mname")以待稍后淬火,甚至可以对"mname:0"进行预处理。



编辑

(由@PaulMcG指出)

此机制直接在pyparsing中实现:

import pyparsing as pp

fname = pp.OneOrMore(pp.Word("Max")).setResultsName("fname")
mname = pp.OneOrMore(pp.Word("Joseph")).setResultsName("mname", listAllMatches=True)
lname = pp.OneOrMore(pp.Word("Andrews")).setResultsName("lname")
another_mname = pp.OneOrMore(pp.Word("Miller")).setResultsName("mname", listAllMatches=True)

full = fname + mname + lname + another_mname

output = full.parseString("Max Joseph Joseph Andrews Miller Miller").asDict()
print(output)
# {'fname': ['Max'], 'mname': [['Joseph', 'Joseph'], ['Miller', 'Miller']], 'lname': ['Andrews']}


甚至像这样:

import pyparsing as pp

fname = pp.OneOrMore(pp.Word("Max")).setResultsName("fname")
mname = pp.OneOrMore(pp.Word("Joseph") | pp.Word("Miller")).setResultsName("mname", listAllMatches=True)
lname = pp.OneOrMore(pp.Word("Andrews")).setResultsName("lname")

full = fname + mname + lname + mname

output = full.parseString("Max Joseph Joseph Andrews Miller Miller").asDict()
print(output)
# {'fname': ['Max'], 'mname': [['Joseph', 'Joseph'], ['Miller', 'Miller']], 'lname': ['Andrews']}


尽管结果是listlist而不是一个扁平的。

关于python - pyparsing中的asDict方法将覆盖先前的键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56936801/

10-16 10:40