解析像这样的纯文本树结构的最佳方法是什么:
node1:
node1
node2:
node1
node2:
node1
node2
node3:
node1:
node1
node2:
node1
node2并将其转换为树形结构(带有列表或字典)?
有没有python库可以帮我解析?
发布于 2015-09-07 01:55:03
rson库可以做到这一点,除非您可能必须对解析器进行子类化,以允许在单个结构中混合使用数组和字典样式的元素。
编辑实际上,这可能有点困难,但rsonlite包将(某种程度上)对您的数据按原样工作。
rsonlite是一个小的、单模块的包,只有300行,相同的源代码适用于Python2和Python3。
下面是一个示例,它显示了数据的3种不同输出。第一个输出是rsonlite.dumps()提供的内容,第二个输出是稍高级别的rsonlite.simpleparse()提供的内容,第三个输出从simpleparse获取结果并通过自定义fixup()函数运行它们,以创建一个纯嵌套字典数据结构,其中任何缺少的值都被简单地设置为None,并且检查并剥离所有冒号字符。
from rsonlite import loads, simpleparse
mystring = '''
node1:
node1
node2:
node1
node2:
node1
node2
node3:
node1:
node1
node2:
node1
node2
'''
def fixup(node):
if isinstance(node, str):
return node
elif isinstance(node, dict):
for key in node:
assert key.endswith(':'), key
return dict((key[:-1], fixup(value)) for key, value in node.items())
else:
assert isinstance(node, (list, str))
result = {}
for item in node:
if isinstance(item, str):
assert not item.endswith(':')
assert result.setdefault(item, None) is None
else:
for key, value in fixup(item).items():
assert result.setdefault(key, value) is value
return result
print('')
print(loads(mystring))
print('')
print(simpleparse(mystring))
print('')
print(fixup(simpleparse(mystring)))
print('')将给予:
[('node1:',['node1',('node2:','node1')]),('node2:',['node1','node2',('node3:',[('node1:','node1'),('node2:','node1',‘node2’)])]
OrderedDict([('node1:',['node1',OrderedDict(('node2:',‘node1’))],('node2:',['node1','node2',OrderedDict([('node3:','node1'),('node2:','node1',‘node2’))])
{'node1':无,'node2':'node1'},'node2':{'node1':无,'node2':无,'node3':{'node1':'node1','node2':{'node1':无,'node2':无}
发布于 2015-09-07 06:45:02
您可以构造一个简单的解析器,该解析器从输入生成有效的python表达式,然后对其求值。我最初的想法是一个简单的递归解析器,但这比我预期的要困难得多,因为他们没有办法知道块是在没有峰值的情况下结束的-这是基于缩进的格式的常见问题。
这将生成元组(block_name、contents)的嵌套列表:
i = 0
r = '['
for l in mystring.split('\n'):
if not l:
continue
cl = l.lstrip(' ')
ci = (len(l) - len(cl))//4
if ci > i: # line indented
r += '['
elif ci < i: # line unindented, can be multiple
r += '])'*(i-ci) + ','
if cl[-1] == ':': # new block
r += '{("{}":'.format(cl[:-1])
else: # new item
r += '"{}",'.format(cl)
i = ci
r += ']'+')]'*i
eval(r)输出:
[('node1', ['node1', ('node2', ['node1'])]),
('node2',
['node1',
'node2',
('node3', [('node1', ['node1']), ('node2', ['node1', 'node2'])])])]https://stackoverflow.com/questions/32426522
复制相似问题