如何在循环中将字典添加到列表中

3

我手头有大量的数据,形式为元组列表。每个元组都有指定的格式,比如(a, b, c, d, e)。元组列表看起来像:

tupleList = [('a1', 'b1', 'c1', 'd1', 'e1'),
             ('a2', 'b2', 'c2', 'd2', 'e2'),
             ...
             ('a10000', 'b10000', 'c10000', 'd10000', 'e100000')]

我希望的是将这些元组转换为字典,并将字典添加到一个最终的字典列表中。所有这些可以在循环中完成吗?最终的字典列表应该如下所示:
finalDictList = [{'key1': 'a1', 'key2': 'b1', 'key3': 'c1', 'key4': 'd1', 'key5': 'e1'},
                 {'key1': 'a2', 'key2': 'b2', 'key3': 'c2', 'key4': 'd2', 'key5': 'e2'},
                 {'key1': 'a3', 'key2': 'b3', 'key3': 'c3', 'key4': 'd3', 'key5': 'e3'},
                 ...
                 {'key1': 'a10000', 'key2': 'b10000', 'key3': 'c10000', 'key4': 'd10000', 'key5': 'e10000'}]

元组的格式是固定的。我希望能够比较字典中每个键的值和其他所有键的值。这就是为什么将元组转换为字典对我来说是有意义的原因。如果设计范式本身有问题,请纠正我。此外,有超过10000个元组。声明那么多的字典是不可行的。
在循环中有没有一种方式可以将字典附加到列表中?如果可能的话,我们能否通过它的键值访问每个字典,比如像 `finalDictList[0]['key1']`这样?
7个回答

10

我们将结合三个重要的概念来使这段代码更加简洁美观。首先是列表推导式,然后是zip方法,最后是字典方法,通过一个由元组组成的列表构建一个字典:

my_list = [('a1', 'b1', 'c1', 'd1', 'e1'), ('a2', 'b2', 'c2', 'd2', 'e2')]
keys = ('key1', 'key2', 'key3', 'key4', 'key5')
final = [dict(zip(keys, elems)) for elems in my_list]

之后,final 变量的值为:

>>> final
[{'key3': 'c1', 'key2': 'b1', 'key1': 'a1', 'key5': 'e1', 'key4': 'd1'},
{'key3': 'c2', 'key2': 'b2', 'key1': 'a2', 'key5': 'e2', 'key4': 'd2'}]

另外,你可以通过字典在列表中的位置和你要查找的键来获取某个字典的元素,例如:

>>> final[0]['key1']
'a1'

@sneha:很高兴能帮到你,如果这篇文章解决了你的问题,你可以选择它作为被采纳的答案(左侧的绿色勾选)。 - juliomalegria

6
使用zip将预定义的键名列表与输入列表中的每个元组结合,然后将结果传递给dict,使它们成为字典。将整个过程包装在列表推导中,以一批处理所有内容:
keys = ('key1', 'key2', 'key3', 'key4', 'key5')
finalDictList = [dict(zip(keys, values)) for values in tupleList]

4

我不确定为什么你需要将所有内容都转换成字典,当你已经有了一个元组列表。

>>> tupleList = [('a1', 'b1', 'c1', 'd1', 'e1'),
...              ('a2', 'b2', 'c2', 'd2', 'e2'),
...              ('a10000', 'b10000', 'c10000', 'd10000', 'e100000')]
>>> [x[1] for x in tupleList]
['b1', 'b2', 'b10000']

使用Python的列表推导式语法,您可以获得每个元组中第n个元素的列表。

我知道这一点,但元组中的条目彼此相关 - 也就是说,(a,b,c,d,e)只有在一起才有意义。我知道这对于比较来说没问题,但如果在比较过程中出现/不出现匹配,我必须处理完整个元组。我可以让它工作,但这将是一个迂回的方式。谢谢! :) - sneha
@sneha:访问元组的元素与访问字典的元素几乎具有相同的语法:x[2] vs x["key2"]。如果您想要,可以定义常量,例如 KEY2 = 2,这样您就可以使用 x[KEY2]。将其转换为字典列表将占用更多的内存,而获得的好处却很少。 - Greg Hewgill
1
嗯...我想你说得很有道理。让我重新考虑我的设计。 :) - sneha

3
如果字段是固定的,您可以这样做:
fields = ['key1', 'key2', 'key3', 'key4', 'key5']

newList = [dict(zip(fields, vals)) for vals in oldList]

2

如果您说您有很多条目,请记住Python有命名元组

>>> tupleList = [('a1', 'b1', 'c1', 'd1', 'e1'),
...              ('a2', 'b2', 'c2', 'd2', 'e2'),
...              ('a10000', 'b10000', 'c10000', 'd10000', 'e100000')]
>>>
>>> from collections import namedtuple
>>> fv = namedtuple('fivevals', ('key1', 'key2', 'key3', 'key4', 'key5'))
>>> tuplelist = [fv(*item) for item in tupleList]
>>> 
>>> tuplelist[0].key1
'a1'
>>>

命名元组可以通过键访问,但与普通元组相比,它们轻量且不需要更多的内存。


啊!我很惭愧,我竟然没记住那个。好提醒! - Kirk Strauser

0
finalDictList = []
for t in tupleList:
    finalDictList.append({
        'key1': t[0],
        'key2': t[1],
        'key3': t[2],
        'key4': t[3],
        'key5': t[4],
    })

如果可能的话,我们能否通过它们的键值访问每个字典,比如finalDictList[0]['key1']?
当然可以,这正是您应该这样做的方式。

0
from itertools import izip

keys = ['key1', 'key2', 'key3', 'key4', 'key5']
finalDictList = [dict(izip(names, x)) for x in tupleList]

为了避免在每次迭代中构建临时列表。 - yak
这似乎是在用生成器的开销来交换一个微小的内存分配。 - Kirk Strauser

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