我有一个像
这样的字符串(0(1(2(3(4(5))(6室))(7(8)(9(10极)(11好)))) (12但))(13(14(15)(16食品))(17(18)(19(20))(21 坏))))))(22。))
实际上是一棵树:
我想获得一个给定节点的字符串,即如果说节点0我应该收到“房间非常好,但食物很糟糕。”如果我说节点2我应该收到“房间非常好”但节点5“The”等等。
答案 0 :(得分:2)
我首先构建一个明显的树(其中节点有子节点和可能的字符串有效负载)然后处理它以获得您想要的替代(使用包含子有效负载的字符串)。例如,草稿(无错误检查& c):
class Node(object):
def __init__(self, n):
self.n = n
self.children = []
self.text = []
self.payload = self.wholestring = ''
def make_payload_tree(astring):
root = Node(-1)
parents = [root]
sit = iter(astring)
for c in sit:
if c=='(':
mkn = []
for c in sit:
if c==' ': break
mkn.append(c)
newnode = Node(int(''.join(mkn)))
parents[-1].children.append(newnode)
parents.append(newnode)
elif c==')':
oldnode = parents.pop()
oldnode.payload = ''.join(oldnode.text)
else:
parents[-1].text.append(c)
return root
您可以粗略地验证此有效负载树是否正确,例如:
def print_tree(r, ind=0):
print ' '*ind, r.n, r.payload, r.wholestring
for c in r.children:
print_tree(c, ind + 2)
当然,此时wholestring
仍为空字符串。
现在,第二遍可以构建wholestring
属性:
def makewhole(node):
for c in node.children:
makewhole(c)
s = node.payload + ' '.join(c.wholestring for c in node.children)
node.wholestring = s.replace(' ', ' ')
并且print_tree
应该验证您拥有所需的wholestring
。
现在有趣的部分是正确的错误诊断(如果输入字符串中存在任何“语法错误”,则此代码非常脆弱,并且您的示例隐含了其语法,从来没有明确表示),但这可能最好用一个合适的词法分析器和解析器方法,而不是像我在这里做的临时解析。
答案 1 :(得分:2)
您可以使用pyparsing解析字符串:
s='(0 (1 (2 (3 (4 (5 The) (6 room)) (7 (8 was) (9 (10 very) (11 good)))) (12 but)) (13 (14 (15 the) (16 food)) (17 (18 was) (19 (20 very) (21 bad))))) (22 .))'
from pyparsing import *
enclosed = Forward()
nestedParens = nestedExpr('(', ')', content=enclosed)
enclosed << (Word(alphanums+'.') | ',' | nestedParens)
>>> enclosed.parseString(s).asList()
[['0', ['1', ['2', ['3', ['4', ['5', 'The'], ['6', 'room']], ['7', ['8', 'was'], ['9', ['10', 'very'], ['11', 'good']]]], ['12', 'but']], ['13', ['14', ['15', 'the'], ['16', 'food']], ['17', ['18', 'was'], ['19', ['20', 'very'], ['21', 'bad']]]]], ['22', '.']]]
然后根据需要处理嵌套数据。
答案 2 :(得分:0)
第一个问题是,如何解析字符串。
每个node
看似({number} {word | node node})
,number
为\d+
,word
为[\w,.]+
。这种描述非常适合递归下降解析器。
第二个问题是,如何存储结果树,以便我可以轻松找到节点及其后代。
我建议按节点编号索引dict
- 类似于
tree = {
0: (1, 22),
1: (2, 13),
2: (3, 12),
# ...
20: "very",
21: "bad",
22: "."
}
这允许您直接跳转到任何节点,并从那里跟随树来重新创建句子片段。