Python - 将字典反扁平化

10 投票
5 回答
9671 浏览
提问于 2025-04-16 17:50

我有一个多维的字典:

a = {'a' : 'b', 'c' : {'d' : 'e'}}

我写了一个简单的函数来把这个字典变成一维的:

def __flatten(self, dictionary, level = []):
    tmp_dict = {}
    for key, val in dictionary.items():
        if type(val) == dict:
            tmp_dict.update(self.__flatten(val, level + [key]))
        else:
            tmp_dict['.'.join(level + [key])] = val
    return tmp_dict

当我用字典 a 调用这个函数后,得到的结果是:

{'a' : 'b', 'c.d' : 'e'}

现在,在对这个一维字典进行了一些操作后,我需要从这个一维字典重新构建一个新的多维字典。举个例子:

>> unflatten({'a' : 0, 'c.d' : 1))
{'a' : 0, 'c' : {'d' : 1}}

我唯一的问题是我没有一个叫 unflatten 的函数 :)
有人能帮我吗?我完全不知道该怎么做。

编辑:

另一个例子:

{'a' : 'b', 'c.d.e.f.g.h.i.j.k.l.m.n.o.p.r.s.t.u.w' : 'z'}

在解压后应该是:

{'a': 'b', 'c': {'d': {'e': {'f': {'g': {'h': {'i': {'j': {'k': {'l': {'m': {'n': {'o': {'p': {'r': {'s': {'t': {'u': {'w': 'z'}}}}}}}}}}}}}}}}}}}

还有一个:

{'a' : 'b', 'c.d' : 'z', 'c.e' : 1}

变成:

{'a' : 'b', 'c' : {'d' : 'z', 'e' : 1}}

我知道这大大增加了任务的难度。这就是我遇到问题的原因,几个小时都没找到解决办法……

5 个回答

4

这里有一个使用了Python 3.5及以上版本的新特性,比如类型注解和解构赋值。你可以在repl.it上试试这些测试

from typing import Any, Dict


def unflatten(
    d: Dict[str, Any], 
    base: Dict[str, Any] = None,
) -> Dict[str, Any]:
    """Convert any keys containing dotted paths to nested dicts

    >>> unflatten({'a': 12, 'b': 13, 'c': 14})  # no expansion
    {'a': 12, 'b': 13, 'c': 14}

    >>> unflatten({'a.b.c': 12})  # dotted path expansion
    {'a': {'b': {'c': 12}}}

    >>> unflatten({'a.b.c': 12, 'a': {'b.d': 13}})  # merging
    {'a': {'b': {'c': 12, 'd': 13}}}

    >>> unflatten({'a.b': 12, 'a': {'b': 13}})  # insertion-order overwrites
    {'a': {'b': 13}}

    >>> unflatten({'a': {}})  # insertion-order overwrites
    {'a': {}}
    """
    if base is None:
        base = {}

    for key, value in d.items():
        root = base

        ###
        # If a dotted path is encountered, create nested dicts for all but
        # the last level, then change root to that last level, and key to
        # the final key in the path.
        #
        # This allows one final setitem at the bottom of the loop.
        #
        if '.' in key:
            *parts, key = key.split('.')

            for part in parts:
                root.setdefault(part, {})
                root = root[part]

        if isinstance(value, dict):
            value = unflatten(value, root.get(key, {}))

        root[key] = value

    return base
4
from collections import defaultdict
def unflatten(d):
    ret = defaultdict(dict)
    for k,v in d.items():
        k1,delim,k2 = k.partition('.')
        if delim:
            ret[k1].update({k2:v})
        else:
            ret[k1] = v
    return ret

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

29

在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要将它们转换成一种程序能处理的格式。

比如说,如果我们从用户那里得到一个数字的字符串(像“123”),我们需要把它转换成真正的数字(123),这样程序才能进行数学运算。这个过程叫做“类型转换”。

在不同的编程语言中,类型转换的方式可能会有所不同。有些语言会自动帮你转换,有些则需要你手动去做。了解这些转换的规则,可以帮助你写出更有效的代码。

总之,处理数据时,确保它们是正确的类型是非常重要的,这样才能避免错误并让程序顺利运行。

def unflatten(dictionary):
    resultDict = dict()
    for key, value in dictionary.items():
        parts = key.split(".")
        d = resultDict
        for part in parts[:-1]:
            if part not in d:
                d[part] = dict()
            d = d[part]
        d[parts[-1]] = value
    return resultDict

撰写回答