我有许多相互对应的列表:
ID_number = [1, 2, 3, 4, 5, 6, ...]
x_pos = [43.2, 53.21, 34.2, ...]
y_pos = [32.1, 42.1, 8.2, ...]
z_pos = [1.3, 67.1, 24.3, ...]
等
我希望能够根据ID_number对数据进行排序,拉取和执行操作,所以我想从这些列表中创建一个字典,
dictionary = {'id1':[x_pos1, y_pos1, z_pos1], 'id2':[x_pos2, y_pos2, z_pos2], ...}
其中键是ID号,值是包含该ID号的相应数据的列表。我如何在python中有效地做到这一点?
答案 0 :(得分:4)
两次使用zip
:
>>> ids = [1,2,3,4]
>>> x_pos = [1.32, 2.34, 5.56, 8.79]
>>> y_pos = [1.2, 2.3, 3.4, 4.5]
>>> z_pos = [3.33, 2.22, 10.98, 10.1]
>>> dict(zip(ids, zip(x_pos, y_pos, z_pos)))
{1: (1.32, 1.2, 3.33), 2: (2.34, 2.3, 2.22), 3: (5.56, 3.4, 10.98), 4: (8.79, 4.5, 10.1)}
与genexp的时序比较:
>>> import timeit
>>> timeit.timeit('dict(zip(ids, zip(x_pos, y_pos, z_pos)))', 'from __main__ import ids, x_pos, y_pos, z_pos')
1.6184730529785156
>>> timeit.timeit('dict((x[0], x[1:]) for x in zip(ids, x_pos, y_pos, z_pos))', 'from __main__ import ids, x_pos, y_pos, z_pos')
2.5186140537261963
因此,使用zip
两次比使用生成器表达式快1.5倍。显然结果取决于迭代的大小,但我非常有信心使用双zip
,至少在CPython 2上总是比显式循环更快。与单for
调用相比,生成器异常或zip
循环需要更多的解释器工作,从而消除了迭代过程中的一些开销。
使用itertools.izip
代替zip
并不会改变很多时间,但对于大数据集来说,内存效率会更高。
答案 1 :(得分:2)
zip()
对于实现这一点非常有用。例如:
>>> ID_number = [1,2,3]
>>> x_pos = [43.2, 53.21, 34.2]
>>> y_pos = [32.1, 42.1, 8.2]
>>> z_pos = [1.3, 67.1, 24.3]
>>> dict((x[0], x[1:]) for x in zip(ID_number, x_pos, y_pos, z_pos))
{1: (43.200000000000003, 32.100000000000001, 1.3), 2: (53.210000000000001, 42.100000000000001, 67.099999999999994), 3: (34.200000000000003, 8.1999999999999993, 24.300000000000001)}
如果数据集非常大,您可以使用itertools.izip()
来避免zip()
创建整个数据集的全新副本。此函数将返回一个迭代器,它将在请求时提供每个压缩元素,而不是将整个新结构保存在内存中。 (结果将是相同的,但在较大的数据集上应该更快。)
>>> import itertools
>>> dict((x[0], x[1:]) for x in itertools.izip(ID_number, x_pos, y_pos, z_pos))
{1: (43.200000000000003, 32.100000000000001, 1.3), 2: (53.210000000000001, 42.100000000000001, 67.099999999999994), 3: (34.200000000000003, 8.1999999999999993, 24.300000000000001)}
答案 2 :(得分:0)
dictionary = {'id' + str(i): [x, y, z]
for i, x, y, z in zip(ID_number, x_pos, y_pos, z_pos)}
使用itertools
'izip()
,对于大型数据集可能会更快