pyparsing 中的 asDict 方法覆盖先前的键
asDict method in pyparsing overrides previous key
我有一个我面临的问题的人为示例:
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']}
很明显为什么输出是这样的。但是,我还想收集 'Joseph' 作为另一个值。例如
# desired output
{'fname': ['Max'], 'lname': ['Andrews'], 'mname': ['Joseph', 'Joseph', 'Miller', 'Miller']}
谢谢。
您的代码不起作用,因为您将结果的名称设置为相同。
这会导致结果 dict()
中与 mname
关联的 "mname"
条目被与 another_mname
.
关联的 "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']}
但出于不同的原因:现在 full
末尾的 mname
正在替换 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']}
或者,通过自动将多个 "mname"
实例转换为 编号的 个实例(例如 "mname:0"
)来预处理 full
稍后淬火。
编辑
(正如@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']}
尽管结果是 list
的 list
而不是一个扁平化的结果。
我有一个我面临的问题的人为示例:
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']}
很明显为什么输出是这样的。但是,我还想收集 'Joseph' 作为另一个值。例如
# desired output
{'fname': ['Max'], 'lname': ['Andrews'], 'mname': ['Joseph', 'Joseph', 'Miller', 'Miller']}
谢谢。
您的代码不起作用,因为您将结果的名称设置为相同。
这会导致结果 dict()
中与 mname
关联的 "mname"
条目被与 another_mname
.
"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']}
但出于不同的原因:现在 full
末尾的 mname
正在替换 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']}
或者,通过自动将多个 "mname"
实例转换为 编号的 个实例(例如 "mname:0"
)来预处理 full
稍后淬火。
编辑
(正如@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']}
尽管结果是 list
的 list
而不是一个扁平化的结果。