逆向操作,把被压平的字典还原成嵌套字典
在使用 yield 压平嵌套字典有多简单?这篇文章中,我们讲到,要把一个多层嵌套的字典压平,可以使用yield
关键字来实现。
今天,我们倒过来,把一个已经被压平的字典还原成嵌套字典。
目标字典为:
1 | { |
我们要把它还原为:
1 | { |
要实现这个需求,我们分成两个主要的步骤。
还原每一个嵌套字典
对于{'a_b_h':1}
,它实际上被还原以后应该是:
1 | {'a': {'b': {'h': 1}}} |
现在,写一个函数unpack
,这个函数的作用是传入两个参数['a', 'b', 'h']
和1
输出{'a': {'b': {'h': 1}}}
:
1 | def unpack(key, value): |
需要注意的是,unpack
函数的第一个参数是一个列表,形如:['a', 'b', 'h']
。运行效果如下图所示。
这个函数使用递归,把第一个参数列表一项一项拿出来,作为字典的 key,并把剩下的项作为子字典的 key。当列表只剩一个值的时候,说明已经到了最里面了,把这个值作为最里面字典的 key,第二个参数作为 value。
接下来,我们实现第二个函数deflat
,它把目标字典分成key, value
对,并把 key 转换为列表以后传给unpack
函数:
1 | def deflat(x): |
在 deflat
函数中,我们传入目标字典。目标字典的每一对 key, value
被取出来,传入unpack
函数构造每一个小的嵌套字典。
运行效果如下图所示:
合并字典
有了每一个嵌套字典以后,我们要做的就是把他们合并起来。
假设我们有两个字典:dst 和 src,把 src 的内容合并到 dst 字典中,有如下几种情况。
dst中没有 src 的 key
假设dst = {'a': 1}
,src = {'b': 1}
,那么合并以后,dst
变成{'a': 1, 'b': 1}
。
对应代码如下:
1 | def merge(dst, src): |
dst 中有 src 的 key且值都是字典
假设dst = {'a': {'b': 1}}
, src = {'a': {'c': 1}}
,那么由于dst
与src
都有'a'
这个 key,所以问题转换为合并{'b': 1}
和{'c': 1}
,变成第一种情况。
对应代码如下:
1 | def merge(dst, src): |
dst 中有 src 的 key 且值相同
在本题中,这种情况不存在,因为这会导致目标字典有相同的 key。但是字典是不能重复的。
dst中有 src 的 key 且值的类型不同
这种情况下说明目标字典有问题,无法合并。
例如:
1 | { |
这种字典不存在嵌套写法,因为{'a': 3}
与{'a': {'b': {'c': 1}}}
只能互相覆盖,不能合并。
完整写法
merge
函数的完整写法如下:
1 | def merge(dst, src): |
解答问题
最后我们来解答这个问题,把三个函数结合起来。运行效果如下图所示:
当传入不能被转换的目标字典时,也会正常报错