[英]How to unpack keys with list of values to multiple dictionaries to a list without overwriting?
I have a list of dictionaries: 我有一个词典列表:
data = [
{'name': 'foo', 'scores': [2]},
{'name': 'bar', 'scores': [4, 9, 3]},
{'name': 'baz', 'scores': [6, 1]}
]
I want to create a new list which has each individual score
separated out like this: 我想创建一个新列表,将每个单独的
score
分开,如下所示:
list = [
{'name': 'foo', 'scores': [2], 'score': 2},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 4},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 9},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 3},
{'name': 'baz', 'scores': [6, 1], 'score': 6},
{'name': 'baz', 'scores': [6, 1], 'score': 1}
]
I can then loop through each row
, and each score
, to create a new dictionary: 然后我可以循环遍历每一
row
和每个score
,以创建一个新的字典:
for row in data:
scores = row['scores'] # list of values
for score in scores:
new_row = row
new_row['score'] = score
print(new_row)
Which gives me exactly what I want: 这给了我我想要的东西:
{'name': 'foo', 'scores': [2], 'score': 2}
{'name': 'bar', 'scores': [4, 9, 3], 'score': 4}
{'name': 'bar', 'scores': [4, 9, 3], 'score': 9}
{'name': 'bar', 'scores': [4, 9, 3], 'score': 3}
{'name': 'baz', 'scores': [6, 1], 'score': 6}
{'name': 'baz', 'scores': [6, 1], 'score': 1}
However, I'm having trouble adding these dictionaries to a list. 但是,我在将这些词典添加到列表时遇到了问题。 When I use the
append()
function to add each dictionary to a new list: 当我使用
append()
函数将每个字典添加到新列表时:
list = []
for row in data:
scores = row['scores'] # list of values
for score in scores:
new_row = row
new_row['score'] = score
list.append(new_row)
print(list)
It seems to overwrite some of the previous items: 它似乎覆盖了以前的一些项目:
[
{'name': 'foo', 'scores': [2], 'score': 2},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 3},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 3},
{'name': 'bar', 'scores': [4, 9, 3], 'score': 3},
{'name': 'baz', 'scores': [6, 1], 'score': 1},
{'name': 'baz', 'scores': [6, 1], 'score': 1}
]
What's going on here? 这里发生了什么? Why is it printing the rows correctly, but overwriting previous items when adding to a list?
为什么正确打印行,但在添加到列表时覆盖以前的项目? I thought
append()
simply adds new items to the end of a list without altering other items? 我以为
append()
只是在列表末尾添加新项而不改变其他项?
Here new_row
always reference the current row
object, that is the same for every score in this row object. 这里
new_row
总是引用当前row
对象,对于此行对象中的每个分数都是相同的。 You need to create a new object copying the current row. 您需要创建一个复制当前行的新对象。 Use
deepcopy
from the copy
package. 从
copy
包中使用deepcopy
。
from copy import deepcopy
for row in data:
scores = row['scores'] # list of values
for score in scores:
new_row = deepcopy(row)
...
How about a simple list comprehension, to achieve all these in a single step: 简单的列表理解如何,只需一步即可实现所有这些:
In [269]: [{**d, **{'score': v}} for d in data for v in d['scores']]
Out[269]:
[{'name': 'foo', 'score': 2, 'scores': [2]},
{'name': 'bar', 'score': 4, 'scores': [4, 9, 3]},
{'name': 'bar', 'score': 9, 'scores': [4, 9, 3]},
{'name': 'bar', 'score': 3, 'scores': [4, 9, 3]},
{'name': 'baz', 'score': 6, 'scores': [6, 1]},
{'name': 'baz', 'score': 1, 'scores': [6, 1]}]
Explanation/Clarification : 说明/澄清 :
This list comprehension does what OP finally needs. 这个列表理解做了OP最终需要的。 We start by iterating over each dictionary in our list of dictionaries
data
and for each value v
in current dictionary's scores
with this nested for
loop, 我们首先迭代字典
data
列表中的每个字典,并使用此嵌套for
循环对当前字典的scores
每个值v
进行迭代,
for d in data for v in d['scores'] # order goes from left to right
we add a key score
and a value v
by unpacking and then we also unpack the current dictionary since OP needs that as well. 我们通过解压缩添加一个关键
score
和一个值v
,然后我们也解压缩当前字典,因为OP也需要它。 At the end we concatenate both of these using {**d, **{'score': v}}
and that's what we need to achieve. 最后,我们使用
{**d, **{'score': v}}
连接这两个,这就是我们需要实现的目标。
The concatenation is done using { }
or dict()
because we unpack the keys and values from both d
and {'score': v}
; 使用
{ }
或dict()
完成连接,因为我们从d
和{'score': v}
解包密钥和值; Thus, an alternative is: 因此,另一种选择是:
In [3]: [dict(**d, **{'score': v}) for d in data for v in d['scores']]
Out[3]:
[{'name': 'foo', 'score': 2, 'scores': [2]},
{'name': 'bar', 'score': 4, 'scores': [4, 9, 3]},
{'name': 'bar', 'score': 9, 'scores': [4, 9, 3]},
{'name': 'bar', 'score': 3, 'scores': [4, 9, 3]},
{'name': 'baz', 'score': 6, 'scores': [6, 1]},
{'name': 'baz', 'score': 1, 'scores': [6, 1]}]
For more details on dictionary unpacking examples, please refer peps/pep-0448/ 有关字典解包示例的更多详细信息,请参阅peps / pep-0448 /
The answers above are great. 上面的答案很棒。 Thanks!
谢谢! Here I just explain the reason of the bug in a simple way.
在这里,我只是简单地解释bug的原因。 I added two print():
我添加了两个print():
for score in scores:
print(row)
new_row = row
new_row['score'] = score
list.append(new_row)
print(list)
part of the results: 部分结果:
......
{'name': 'bar', 'scores': [4, 9, 3]}
[{'name': 'foo', 'scores': [2], 'score': 2}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 4}]
{'name': 'bar', 'scores': [4, 9, 3], 'score': 4}
[{'name': 'foo', 'scores': [2], 'score': 2}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 9}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 9}]
{'name': 'bar', 'scores': [4, 9, 3], 'score': 9}
[{'name': 'foo', 'scores': [2], 'score': 2}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 3}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 3}, {'name': 'bar', 'scores': [4, 9, 3], 'score': 3}]
......
So now we can see when new_row = row
, they refer to the same object. 所以现在我们可以看到
new_row = row
,它们引用同一个对象。 When new_row changes, row also changes. 当new_row更改时,行也会更改。 The list result is the result of the last loop for each
scores
. 列表结果是每个
scores
的最后一个循环的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.