逆向操作,把被压平的字典还原成嵌套字典

简介: 逆向操作,把被压平的字典还原成嵌套字典

摄影:产品经理

与产品经理的亲子时间

使用 yield 压平嵌套字典有多简单?这篇文章中,我们讲到,要把一个多层嵌套的字典压平,可以使用yield关键字来实现。

今天,我们倒过来,把一个已经被压平的字典还原成嵌套字典。

目标字典为:

{
    'a_b_h':1,
    'a_b_i':2,
    'a_c_j':3,
    'a_d':4,
    'a_c_k':5,
    'a_e':6
}

我们要把它还原为:

{
  "a": {
    "b": {
      "h": 1,
      "i": 2
    },
    "c": {
      "j": 3,
      "k": 5
    },
    "d": 4,
    "e": 6
  }
}

要实现这个需求,我们分成两个主要的步骤。

还原每一个嵌套字典

对于{'a_b_h':1},它实际上被还原以后应该是:

{'a': {'b': {'h': 1}}}

现在,写一个函数unpack,这个函数的作用是传入两个参数['a', 'b', 'h']1输出{'a': {'b': {'h': 1}}}

def unpack(key, value):
    if len(key) == 1:
        return {key[0]: value}
    else:
        prefix = key.pop(0)
        return {prefix: unpack(key, value)}

需要注意的是,unpack函数的第一个参数是一个列表,形如:['a', 'b', 'h']。运行效果如下图所示。

这个函数使用递归,把第一个参数列表一项一项拿出来,作为字典的 key,并把剩下的项作为子字典的 key。当列表只剩一个值的时候,说明已经到了最里面了,把这个值作为最里面字典的 key,第二个参数作为 value。

接下来,我们实现第二个函数deflat,它把目标字典分成key, value对,并把 key 转换为列表以后传给unpack函数:

def deflat(x):
    for key, value in x.items():
        yield unpack(key.split('_'), value)

deflat函数中,我们传入目标字典。目标字典的每一对 key, value被取出来,传入unpack函数构造每一个小的嵌套字典。

运行效果如下图所示:

合并字典

有了每一个嵌套字典以后,我们要做的就是把他们合并起来。

假设我们有两个字典:dst 和 src,把 src 的内容合并到 dst 字典中,有如下几种情况。

dst 中没有 src 的 key

假设dst = {'a': 1}src = {'b': 1},那么合并以后,dst变成{'a': 1, 'b': 1}

对应代码如下:

def merge(dst, src):
    for key, value in src.items():
        if key notin dst:
            dst[key] = value

dst 中有 src 的 key 且值都是字典

假设dst = {'a': {'b': 1}}src = {'a': {'c': 1}},那么由于dstsrc都有'a'这个 key,所以问题转换为合并{'b': 1}{'c': 1},变成第一种情况。

对应代码如下:

def merge(dst, src):
    for key, value in src.items():
        if key in dst:
            merge(dst[key], value)

dst 中有 src 的 key 且值相同

在本题中,这种情况不存在,因为这会导致目标字典有相同的 key。但是字典是不能重复的。

dst 中有 src 的 key 且值的类型不同

这种情况下说明目标字典有问题,无法合并。

例如:

{
 'a_b_c': 1
 'a': 2
}

这种字典不存在嵌套写法,因为{'a': 3}{'a': {'b': {'c': 1}}}只能互相覆盖,不能合并。

完整写法

merge函数的完整写法如下:

def merge(dst, src):
    for key, value in src.items():
        if key notin dst:
            dst[key] = value
        elif isinstance(dst[key], dict) and isinstance(value, dict):
            merge(dst[key], value)
        else:
            raise Exception('数据格式有误,不能转换为嵌套字典')

解答问题

最后我们来解答这个问题,把三个函数结合起来。运行效果如下图所示:

当传入不能被转换的目标字典时,也会正常报错

目录
相关文章
|
7月前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
|
8月前
|
存储 索引
DAY-2 | 哈希思想:求字符串包含的字符集合
这是一个关于代码实现的问题,主要展示了两种利用哈希思想去除字符串中重复字符的方法。第一种方法使用了`boolean[] flg`数组来标记字符是否出现过,遍历字符串时,如果字符未出现则添加到结果并标记为已出现。第二种方法使用`char[] ch`数组直接存储字符出现状态,先遍历一次字符串记录出现过的字符,再遍历一次输出未标记的字符。
42 0
|
8月前
|
存储
函数——使用字典存储查找人名
函数——使用字典存储查找人名
|
8月前
【全网最简短代码】筛选出新数组中和旧数组的重复项,并和旧数组合并(往数组追加新的数据对象且去重,合并两个数组不重复数据)
【全网最简短代码】筛选出新数组中和旧数组的重复项,并和旧数组合并(往数组追加新的数据对象且去重,合并两个数组不重复数据)
|
8月前
|
存储 C# C++
C# 笔记2 - 数组、集合与与文本文件处理
C# 笔记2 - 数组、集合与与文本文件处理
82 0
元组和列表转换成字典
元组和列表转换成字典
67 0
|
存储 索引 Python
22.从入门到精通:Python数据结构元组和序列 元组 序列 集合 创建集合 集合操作 字典 遍历技巧
22.从入门到精通:Python数据结构元组和序列 元组 序列 集合 创建集合 集合操作 字典 遍历技巧
字符串&列表&元组&字典之间互转
字符串&列表&元组&字典之间互转
|
开发者 Python
把对象当作字典操作 | 学习笔记
快速学习把对象当作字典操作
把对象当作字典操作 | 学习笔记
|
开发者 Python
字典的遍历|学习笔记
快速学习字典的遍历
字典的遍历|学习笔记