0

我应该如何定义一个parsedic()像这样工作的函数?

dic={0:0,
     1:{0:0,
        1:1,
        2:{0:0,},},
     2:{0:{1:0,
           0:{0:0}},},
     3:0}

def parsedic(...):
    ...

print parsedic(dic)

结果

0->0
3->0
1.0->0
1.1->1
1.2.0->0
2.0.0.0->0
2.0.1->0

dict的key的类型只能是数字或字符串,value只能是数字、字符串或dict。

(为了避免误解,我删除了显示我长期以来如何尝试解决这个问题的文字。)

4

2 回答 2

7

“扁平化” dict 的最简单方法是这样的递归生成器:

def parse(dic):
    for k, v in dic.items():
        if isinstance(v, dict):
            for p in parse(v):
                yield [k] + p
        else:
            yield [k, v]

lst = list(parse(dic))

这将创建一个列表列表[[key,key,key,value],[key,key,val] etc],对于您的示例,它将是:

[[0, 0], [1, 0, 0], [1, 1, 1], [1, 2, 0, 0], [2, 0, 0, 0, 0], [2, 0, 1, 0], [3, 0]]

要以所需格式打印,只需遍历此列表:

for row in parse(dic):
    row = map(str, row)
    print '.'.join(row[:-1]) + '->' + row[-1]

这回答了您的问题,但是如果您首先告诉我们为什么需要这种转换,将会很有帮助。也许有更好的方法。

于 2013-10-08T13:13:35.793 回答
4

这种方法可以跟踪路径上的当前键,该路径不是字典。

def parsedic(d,currHist=[]):
    for k,v in d.items(): #go over dict's key,value pairs
        newHist = currHist + [k] #add the current key to the 'path' of keys
        if isinstance(v,dict): #if that value is a dictionary then we need to go over it's key/vals                 
            parsedic(v,currHist=newHist) #recurse...
        else:  #base case
            print "%s->%d"%('.'.join(map(str,newHist)),v) #print out the path separated by '.' and then -> to the value

parsedic(dic)

输出(注意它的顺序不同,因为键值对的迭代会不同):

>>> 
0->0
1.0->0
1.1->1
1.2.0->0
2.0.0.0->0
2.0.1->0
3->0

在每次递归时不创建新列表的稍微难以阅读的方法是:

    currHist.append(k) #add the current key
    if isinstance(v,dict):
        parsedic(v,currHist=currHist)
    else:
        print "%s->%d"%('.'.join(map(str,currHist)),v)
    currHist.pop() #remove that same key
于 2013-10-08T13:02:55.330 回答