如何用Pythonic的方式在列表中设置字典的字段

3

我有两个列表,一个包含整数值:

values = [5,10,15,20]

另一个是字典列表:
dicts = [{'a':0, 'b':0, 'c':0},
         {'a':0, 'b':0, 'c':0},
         {'a':0, 'b':0, 'c':0},
         {'a':0, 'b': 0, 'c':0}]

我希望从值列表中获取第一个值,并将第一个字典的字段"a"设置为来自"values"列表的值,以此类推。换句话说,输出应该是:
dicts = [{'a':5, 'b':0, 'c':0},
         {'a':10, 'b':0, 'c':0},
         {'a':15, 'b':0, 'c':0},
         {'a':20, 'b': 0, 'c':0}]

这该怎么用Python实现呢?

1
bc键怎么办?它们的值会保持为0吗? - Ma0
你对字典的语法有问题。 - Willem Van Onsem
3个回答

4

你可以使用 zip 来为每个字典设置 'a' 的值。示例代码如下:

for dic,val in zip(dicts,values):
    dic['a'] = val

或者用一个单行的表述:

for dic,val in zip(dicts,values): dic['a'] = val

请注意,与前面的代码片段相比,没有任何区别。这取决于你最喜欢哪个。
我们在这里更新字典:我们不创建副本等。这是一个重要的区别,因为可以引用给定字典的变量将反映我们所做的更改。 zip(..) 以一个序列或多个可迭代对象(此处为dictsvalues)作为输入,并生成来自这些可迭代对象的元素的元组。因此,它会发出:
(values[0],dicts[0]), (values[1],dicts[1]), ...

现在我们进行元组解包:我们将valdicvaluesdicts之一进行统一。对于每个元组,我们都设置dic['a']的值。
控制台测试:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> values = [5,10,15,20]
>>> dicts = [{'a':0, 'b':0, 'c':0},
...          {'a':0, 'b':0, 'c':0},
...          {'a':0, 'b':0, 'c':0},
...          {'a':0, 'b': 0, 'c':0}]
>>> for dic,val in zip(dicts,values): dic['a'] = val
... 
>>> dicts
[{'b': 0, 'c': 0, 'a': 5}, {'b': 0, 'c': 0, 'a': 10}, {'b': 0, 'c': 0, 'a': 15}, {'b': 0, 'c': 0, 'a': 20}]

6
实际上,不要将它放在一行下面,错误地认为这会带来某种好处。其实不会。 - chepner
@chepner:就Python解析器而言,据我所知,它们没有任何区别。但是它更加紧凑。 - Willem Van Onsem
1
非常感谢您的答案。这确实是我在寻找的内容。 - Berkay Dincer

1
为了实现Pythonic的一行代码(尽管我强烈建议您优先选择Willem的答案以获得更好的清晰度/可读性):
dicts = [{key: val if key != 'a' else z_val 
            for key, val in d.items()} for d, z_val in zip(dicts, values)]

dicts
Out[5]: 
[{'a': 5, 'b': 0, 'c': 0},
 {'a': 10, 'b': 0, 'c': 0},
 {'a': 15, 'b': 0, 'c': 0},
 {'a': 20, 'b': 0, 'c': 0}]

编辑:删除了字典键的冗余if else。

请注意,这将创建字典的副本。这可能是一个重要的区别,因为引用字典的其他变量不会反映出更改。(我并不是说这是一个问题,但值得注意一下)。 - Willem Van Onsem
@StefanPochmann 我刚刚也在看那个... 有点多余,是吧?感谢你指出来。 - blacksite

0
尝试这段代码:
values = [5,10,15,20]
dicts = [{'a':0, 'b':0, 'c':0},
         {'a':0, 'b':0, 'c':0},
         {'a':0, 'b':0, 'c':0},
         {'a':0, 'b': 0, 'c':0}]

res1 =  dict(zip(dicts[0],zip(*[d.values() for d in dicts])))# tronspose a list of dicts /// res1 = {'a': (0, 0, 0, 0), 'c': (0, 0, 0, 0), 'b': (0, 0, 0, 0)}
res1['a'] = values
res = [dict(zip(res1,t)) for t in zip(*res1.values())]# tronspose res1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接