从缩进文本输入创建嵌套字典

时间:2015-10-19 00:31:57

标签: python

我有一个文本输入,格式为

var="""
interface A
  member-1
  member-2
    submember-1
    submember-2
interface B
  member-1
interface C

"""

我必须将其转换为python嵌套字典形式,如下所示。并且任何没有子成员的元素都将被赋值为-1。

result=
{
'interface A':{'member-1': -1 ,'member-2':{'submember-1': -1,'submember-2': -1}}
'interface B' :{'member-1': -1},
'interface C': -1
}

我试图以递归方式进行,但似乎没有让我的逻辑正确。什么是最佳/ pythonic方式来做到这一点。

2 个答案:

答案 0 :(得分:1)

它有点难看,但如果你没有太多的缩进级别,这段代码可能很有用

_dict = {}
for line in var.split('\n'):
    if line.strip():
        print line
        leading_spaces = len(line) - len(line.lstrip())
        if leading_spaces == 0:
            interface = line.strip()
            _dict[interface] = -1
        elif leading_spaces == 2:
            member = line.strip()
            if _dict[interface] == -1:
                _dict[interface] = {member:-1}
            else:
                _dict[interface].update({member:-1})
        elif leading_spaces == 4:
            print _dict
            submember = line.strip()
            if _dict[interface][member] == -1:
                _dict[interface][member] = {submember:-1}
            else:
                _dict[interface][member].update({submember:-1})

答案 1 :(得分:0)

递归对于这样的事情来说是一个很好的策略,虽然有点复杂,因为a)你必须跟踪你当前正在处理的输入字符串中的哪一行,并且b)你必须先偷看并寻找在未来行的缩进级别,以确定何时应返回特定的递归调用。

一种解决方案是使用生成器来获取连续的行,以及使用当前行和行生成器的递归函数,并返回字典和“下一行”。

from collections import namedtuple
LineData = namedtuple('LineData', 'indent text')

def yield_linedata(text):
    yield LineData(indent=-1, text='')
    for line in text.split('\n'):
        if line.strip() != '':
            yield LineData(indent=len(line)-len(line.lstrip()), text=line.strip())
    yield LineData(indent=-1, text='')

def create_dict(cur_ld, line_yielder):
    next_ld = next(line_yielder)
    if cur_ld.indent >= next_ld.indent:
        return -1, next_ld    
    d = {}
    while cur_ld.indent < next_ld.indent:
        d[next_ld.text], next_ld = create_dict(next_ld, line_yielder)
    return d, next_ld

line_yielder = yield_linedata(var)
cur_ld = next(line_yielder)
result, next_line = create_dict(cur_ld, line_yielder)
print result