【问题标题】:Creating nested dict from dict with nested tuples as keys using comprehension使用理解从 dict 创建嵌套 dict,其中嵌套元组作为键
【发布时间】:2017-03-01 00:54:27
【问题描述】:

今年早些时候我在这里得到了一个非常有用的答案,但是我可以使用 pandas。现在我必须用纯 Python 来做。

有一个这样的字典:

inp = {((0, 0), 0): -99.94360791266038,
       ((0, 0), 1): -1.1111111111107184,
       ((1, 0), 0): -1.111111111107987,
       ((1, 0), 1): -1.1111111111079839,
       ((1, 0), 3): -1.111111111108079}

现在我想将它转换成这样的嵌套字典:

out = {(0,0): {0: -99.94360791266038, 1: -1.1111111111107184},
       (1,0): {0: -1.111111111107987,
               1: -1.1111111111079839,
               3: -1.111111111108079}

如何通过优雅的用词理解来做到这一点?我就是想不通。

【问题讨论】:

    标签: python dictionary nested tuples list-comprehension


    【解决方案1】:

    天真的解决方案:

    my_dict = {
                ((0, 0), 0): -99.94360791266038,
                ((0, 0), 1): -1.1111111111107184,
                ((1, 0), 0): -1.111111111107987,
                ((1, 0), 1): -1.1111111111079839,
                ((1, 0), 3): -1.111111111108079
            }
    
    def get_formatted_dict(my_dict):
        formatted_dict = {}
        for k, v in my_dict.items():
            index_1, index_2 = k
            if index_1 not in formatted_dict:
                formatted_dict[index_1] = {}
            formatted_dict[index_1][index_2] = v
        return formatted_dict
    
    print(get_formatted_dict(my_dict))
    

    输出:

    {(1, 0): {0: -1.111111111107987, 1: -1.1111111111079839, 3: -1.111111111108079}, (0, 0): {0: -99.94360791266038, 1: -1.1111111111107184}}
    

    【讨论】:

    • 一点也不天真;它与我的完全相同,唯一的区别是我使用 dict.setdefault() method 获得与 index_1 not in formatted_dict: 测试相同的行为。
    • 是的。显然,我后来看到了你的答案。
    【解决方案2】:

    我不会用听写理解来做这件事。只需使用一个简单的循环:

    out = {}
    for key, value in inp.items():
        k1, k2 = key
        out.setdefault(k1, {})[k2] = value
    

    演示:

    >>> inp = {((0, 0), 0): -99.94360791266038,
    ...        ((0, 0), 1): -1.1111111111107184,
    ...        ((1, 0), 0): -1.111111111107987,
    ...        ((1, 0), 1): -1.1111111111079839,
    ...        ((1, 0), 3): -1.111111111108079}
    >>> out = {}
    >>> for key, value in inp.items():
    ...     k1, k2 = key
    ...     out.setdefault(k1, {})[k2] = value
    ...
    >>> from pprint import pprint
    >>> pprint(out)
    {(0, 0): {0: -99.94360791266038, 1: -1.1111111111107184},
     (1, 0): {0: -1.111111111107987,
              1: -1.1111111111079839,
              3: -1.111111111108079}}
    

    可以对字典理解做同样的事情,但是您需要对键进行排序并使用itertools.groupby() 将键分组到第一个元组元素上。排序需要 O(NlogN) 时间,并且像上面这样的简单循环很容易击败。

    不过,为了完整起见:

    from itertools import groupby
    out = {g: {k[1]: v for k, v in items} 
           for g, items in groupby(sorted(inp.items()), key=lambda kv: kv[0][0])}
    

    【讨论】:

    • 可以删除带有for (k1, k2), value in inp.items(): 的行,但我想这不太可读。
    • @PM2Ring:是的,我不想使用它,因为我必须解释解包的工作原理。
    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多