我正在努力解决基本的递归pyparsing问题。第一个问题是为什么要添加一个额外的元组层,第二个问题是它为什么不拆分list_pattern
元素。
def parse_tree_to_dict(data):
import pyparsing as pp
_printables = list(pp.printables) + [" "]
_printables = "".join([x for x in _printables if x not in ["|", "}", "{"]])
word_pattern = pp.Word(_printables)
list_pattern = pp.delimitedList(pp.OneOrMore(word_pattern), "|")
itemlist = pp.dictOf(list_pattern, pp.nestedExpr("{", "}"))
items = itemlist.parseString(data)
# print(items.dump())
print(items.asDict())
return items.asDict()
if __name__ == "__main__":
s = "a1{a3|b3}"
data = parse_tree_to_dict(s)
当你运行它时,你得到这个:
{'a1': (['a3|b3'], {})}
所以元组来自哪里,以及为什么list_pattern
没有分开 - 我至少会有预期
{'a1': ['a3', 'b3']}
当我们添加更复杂的结构时,递归组件似乎正在工作,但是会出现相同的基本问题。
s = "a1{b2{a3|b3}c2{d3|e3}e2{a4}}b1{a6|b7}"
data = parse_tree_to_dict(s)
这将导致
{'a1': (['b2', (['a3|b3'], {}), 'c2', (['d3|e3'], {}), 'e2', (['a4'], {})], {}), 'b1': (['a6|b7'], {})}
任何人都可以帮助我吗?谢谢你的期待......
答案 0 :(得分:1)
你有几个踩在一起的表情。您可以尝试为dict值定义list_pattern,但是在定义dictOf时,可以使用list_pattern作为键,使用通用nestedExpr作为值。 nestedExpr不会对' |'做任何特别的事情。分隔符,它只是在' {' '}'嵌套字符并为其提供可打印字词的列表。因为' a3 | b3'没有空格,nestedExpr只是将它作为一个单词返回。
在我看来,你的dict是由一个单词组成的键组成,后跟一个可能嵌套的子句。这是实现这一目标的第一步(我不认为这将完全为您提供嵌套的dict输出,但它是一个开始):
list_pattern = pp.Forward()
LBR,RBR = map(pp.Suppress,"{}")
list_pattern << pp.delimitedList(pp.OneOrMore(word_pattern|pp.Group(LBR+list_pattern+RBR)), "|")
itemlist = pp.dictOf(word_pattern, list_pattern)
这将解析您的数据,并为您提供&#39; a3&#39;的值列表。和&#39; b3&#39;。
{'a1': (['a3', 'b3'], {})}
你问题的第二部分是&#34;那个元组来自哪里?&#34;好吧, 没有元组,你看到的是pyparsing的ParseResults类型的完整repr输出。由于ParseResults提供了解析标记列表和命名结果的双重接口,因此它的repr是标记的元组和结果名称的字典。
如果我们尝试按键访问第一项的值,您可以更清楚地看到这一点:
print data.keys()[0]
print data[data.keys()[0]] # or print data['a1']
打印
a1
['a3', 'b3']
您始终可以使用asList()将ParseResults折叠到实际列表。
另外,查看Word类的新构造函数参数excludeChars。使用printables 中的所有字符(除外)可以更容易地定义Word,以便排除少数字。