【问题标题】:Unpacking multiple values from a nested dictionary in one line "pythonically"在一行中“以python方式”从嵌套字典中解压缩多个值
【发布时间】:2022-01-13 19:01:42
【问题描述】:

假设我有一个如下所示的嵌套字典:

numbers = { 
    'one': {"square": "one", "cube": "one"},
    'two': {"square": "four", "cube": "eight"},
    'three': {"square": "nine", "cube": "twenty-seven"},
    'four': {"square": "sixteen", "cube": "sixty-four"}
}

我想将正方形和立方体解压缩到列表中。我可以这样做:

squares = [n["square"] for n in numbers.values()]
cubes = [n["cube"] for n in numbers.values()]

但这对于重复的代码似乎不太令人满意。我也可以引入 numpy 并这样做:

import numpy
squares_array, cubes_array = numpy.array([(n["square"],n["cube"]) for n in numbers.values()]).T

这巧妙地将所有内容解包到 numpy 数组中,但看起来有点不令人满意,因为我不需要 numpy 来执行此操作,并且在我高度主观的意见中,最后进行转置有点奇怪。对我来说,这似乎不是“pythonic”。

所以问题是我如何在没有 numpy 的情况下在一行中做到这一点?

【问题讨论】:

    标签: python dictionary nested unpack


    【解决方案1】:
    squares, cubes = zip(*[(n["square"], n["cube"]) for n in numbers.values()])
    

    【讨论】:

    • 为了好玩的小变化。将from operator import itemgetter 添加到文件顶部,然后执行:squares, cubes = zip(*map(itemgetter('square', 'cube'), numbers.values()))(如果结果必须是list,则更改为squares, cubes = map(list, zip(*map(itemgetter('square', 'cube'), numbers.values()))),而不是tuple)。
    【解决方案2】:

    你可以使用zip 和一个迭代器:

    squares, cubes = map(list, zip(*(d.values() for d in numbers.values())))
    

    如果有更多键或不同的顺序,请手动指定它们:

    squares, cubes = map(list, zip(*([d['square'], d['cube']]
                                     for d in numbers.values())))
    

    输出:

    >>> squares
    ['one', 'four', 'nine', 'sixteen']
    
    >>> cubes
    ['one', 'eight', 'twenty-seven', 'sixty-four']
    

    【讨论】:

    • 注意:这个解决方案非常脆弱(在 CPython 3.6 之前作为实现细节,3.7 作为语言保证之前根本不起作用)。如果dicts 没有统一定义,'square' 键始终插入'cube' 之前,并且 这两个键,结果将不正确。它适用于 OP 的示例输入,但我不会依赖它。
    • @ShadowRanger 我想这是假设,如果没有人可以指定要保留的密钥(请参阅更新)
    猜你喜欢
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    • 2021-12-31
    • 2018-01-29
    相关资源
    最近更新 更多