繁体   English   中英

列表理解以创建字典的 n 个唯一副本

[英]list comprehension to create n unique copies of a dictionary

我有两个字典键列表:“外部”字典键列表和“内部”字典键列表:

outer_keys = ['out1', 'out2', 'out3', 'out4' ]
inner_keys = ['in1', 'in2', 'in3' ]

我正在尝试使用列表理解以编程方式生成类似于以下结构的嵌套字典:

{'out1': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out2': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out3': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')},
 'out4': {'in1': Decimal('0.00'), 'in2': Decimal('0.00'), 'in3': Decimal('0.00')}
}

我的第一次尝试如下:

from decimal import Decimal
outer_keys = ['out1', 'out2', 'out3', 'out4' ]
inner_keys = ['in1', 'in2', 'in3' ]

z = dict(zip(outer_keys, [dict(zip(inner_keys, [Decimal('0.00') for _ in inner_keys])) for _ in outer_keys]))

这可以正常工作,因为“外部”键引用的“内部”字典都是唯一的:

>>> z['out1']['in1'] is z['out2']['in1']
False

然而,分配给 z 是相当困难的。 所以我试着把它分成两个任务来简化它:

x = dict(zip(inner_keys, [Decimal('0.00') for _ in inner_keys]))
y = dict(zip(outer_keys, [x for _ in outer_keys]))

这不再有效,因为“外部”键“out1”、...、“out4”的值都引用了同一个字典。

>>> y['out1']['in1'] is y['out2']['in1']
True

因此,分配给一个内部字典中的项目会更改它们中的相应值:

>>> y['out1']['in1']
Decimal('0.00')
>>> y['out2']['in1']
Decimal('0.00')
>>> y['out1']['in1']=Decimal('1.00')
>>> y['out2']['in1']
Decimal('1.00')
>>> 

我已经尝试在分配给y的列表理解中使用我能想到的所有东西来代替x (包括例如copy.deepcopy(x)和类似[x][:][0]的列表切片,但无论我做什么,我都无法让 python 为每个外部键值创建由 x 引用的字典的唯一副本。当然,除了返回到 z 的原始冗长且不可读的分配。

我也很难理解为什么[Decimal('0.00') for _ in inner_keys]生成三个唯一的 Decimal 对象,但[x for _ in outer_keys]生成对单个字典的四个引用。 以及如何编写一个列表理解,它将生成 dict xn 个唯一副本。

编辑1:似乎我在检查我尝试过的某些事情是否真的有效时不够小心。 正如@MichaelButscher 在他下面的评论中正确指出的那样,在分配给y时使用x.copy()而不是x将解决我的问题,因此即使我没有意识到它似乎也是copy.deepcopy(x)在职的。

所以这当然是我可以解决这个问题的一种方法。

我也喜欢@Ahmed I. Elsayed 在下面发布的听写理解解决方案。

这两个都比我最初对z的复杂分配要干净得多

Python 提供 dict 理解(也可以设置组合!)

# IDLE ( I reformatted )

my_dict = { key: inner_keys for key in outer_keys }
my_dict

{
 'out1': ['in1', 'in2', 'in3'],
 'out2': ['in1', 'in2', 'in3'],
 'out3': ['in1', 'in2', 'in3'],
 'out4': ['in1', 'in2', 'in3']
}

如果您想像使用Decimal一样将某些内容应用于第二个列表,多种方式

my_dict = { key: [i.upper() for i in inner_keys ] for key in outer_keys }
my_dict

{
 'out1': ['IN1', 'IN2', 'IN3'],
 'out2': ['IN1', 'IN2', 'IN3'],
 'out3': ['IN1', 'IN2', 'IN3'],
 'out4': ['IN1', 'IN2', 'IN3']
}

或者

my_dict = { key: map(str.upper, inner_keys) for key in outer_keys }
# same output as above, trimmed for readability

根据需要进行定制,或在此处的评论中提问。

我想感谢我在哪里学习dictcomps ,我第一次看到它们是在天才 Luciano Ramalho 的一本很棒的书Fluent Python中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM