python生成器经典应用——The Flat Dictonary(扁平字典)问题

题目来源The Flat Dictionary

一.题目

You are given a dictionary where the keys are strings and the values are strings or dictionaries. The goal is flatten the dictionary, but save the structures in the keys. The result should be the a dictionary without the nested dictionaries. The keys should contain paths that contain the parent keys from the original dictionary. The keys in the path are separated by a “/”. If a value is an empty dictionary, then it should be replaced by an empty string (""). Let’s look at an example:

大致题意

对于一个字典,其键为字符串,其值可能为字符串有可能是一个字典。我们的目标是展平这种字典,但是需要保存键中的结构。结果字典应当是一个不包含嵌套字典的字典(称为扁平字典)。扁平字典的键应当包含原始字典的父键的理解。路径中的键使用"/“分隔。如果原始字典中某个原始的值为空字典,应该用空字符串”"代替它。

题目示例
{
    "name": {
        "first": "One",
        "last": "Drone"
    },
    "job": "scout",
    "recent": {},
    "additional": {
        "place": {
            "zone": "1",
            "cell": "2"}
    }
}

The result will be:

{"name/first": "One",           #one parent
 "name/last": "Drone",
 "job": "scout",                #root key
 "recent": "",                  #empty dict
 "additional/place/zone": "1",  #third level
 "additional/place/cell": "2"}

二.解题大致思路

  • 对于本题,由于要消除嵌套字典,利用递归很方便。
  • 由于要保存原始字典中的键结构,因此添加了变量用来保存在不断往深度递归过程中的各级键(用"分隔"),使之成为一个“路径”。
  • 递归过程若当前元素是一个字典则遍历其中所有键值对,在遍历过程中需要添加当前遍历的键值对的键到“路径”中去,然后继续对键值对中的值继续进行递归,直到当前元素不再是一个字典位置,这时yield值和“路径”。

:若对生成器不熟悉可以看一下博主的这篇文章:关于迭代器和生成器,你该了解这些,作为一名python爱好者,生成器绝对一门利器。

三.代码

def disdepth(dit,pre):
    """
    消除嵌套的生成器
    dit:当前元素,可能为字典,有可能是字典中的一个键值对
    pre:父路径
    """
    if type(dit) == dict:#dit是字典
      for key,value in dit.items():
        if value == {}:#键值对中的值为空字典用""代替
          value = ""
        if pre and pre[-1]!='/':#用'/'分隔路径
          pre += '/'
        yield from disdepth(value,pre + key)
    else:#dit为一个值,pre到它位置的父键构成的路径
        yield pre,dit 

def flatten(dictionary):
    out = {}
    for key,value in disdepth(dictionary,''):
        out[key] = value
    return out


if __name__ == '__main__':
    test_input = {"key": {"deeper": {"more": {"enough": "value"}}}}
    print(' Input: {}'.format(test_input))
    print('Output: {}'.format(flatten(test_input)))

    #These "asserts" using only for self-checking and not necessary for auto-testing
    assert flatten({"key": "value"}) == {"key": "value"}, "Simple"
    assert flatten(
        {"key": {"deeper": {"more": {"enough": "value"}}}}
    ) == {"key/deeper/more/enough": "value"}, "Nested"
    assert flatten({"empty": {}}) == {"empty": ""}, "Empty value"
    assert flatten({"name": {
                        "first": "One",
                        "last": "Drone"},
                    "job": "scout",
                    "recent": {},
                    "additional": {
                        "place": {
                            "zone": "1",
                            "cell": "2"}}}
    ) == {"name/first": "One",
          "name/last": "Drone",
          "job": "scout",
          "recent": "",
          "additional/place/zone": "1",
          "additional/place/cell": "2"}
    print('You all set. Click "Check" now!')

若有什么问题欢迎指出,倘若觉得不错希望多多支持!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯曦巍峨

码文不易,有条件的可以支持一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值