从列表列表中的第一个元素中创建一个字典

时间:2015-01-28 13:27:11

标签: python python-2.7 set list-comprehension dictionary-comprehension

这是一个关于在词典理解中使用 set()对列表理解的表现的问题Vs字典理解和重复分配到新词典

所以我碰巧有一个列表列表的数据集,我需要获得一个唯一的元素列表,这些元素在' 0'在大列表中的每个列表中,以便能够从它们创建一个新的字典..像dict.fromkeys()..这里我需要提供唯一键列表..

我正在使用

[1] { x : [] for x in set([i[0] for i in data])}

并且还使用

[2] { i[0] : [] for i in data}

此处参考的样本数据可能如下: [[1,3,4], [3,5,2], [1,5,2]]

上面运行[1]和[2]的结果将是: { 1:[], 3: [] }

我在两个语句上尝试了%timeit,两者都给出了几乎相同的结果,这使得很难确定哪个是最佳的,性能方面的,对于大的列表列表

我如何识别潜在的瓶颈?

修改

如果这有助于解释结果..

In [172]: data_new = data * 10000

In [173]: %timeit { i[0] : [] for i in data_new}
10 loops, best of 3: 160 ms per loop

In [174]: %timeit { x : [] for x in set([i[0] for i in data_new])}
10 loops, best of 3: 131 ms per loop

In [175]: data_new = data * 100000

In [176]: %timeit { x : [] for x in set([i[0] for i in data_new])}
1 loops, best of 3: 1.37 s per loop

In [177]: %timeit { i[0] : [] for i in data_new}
1 loops, best of 3: 1.58 s per loop

In [178]: data_new = data * 1000000

In [179]: %timeit { i[0] : [] for i in data_new}
1 loops, best of 3: 15.8 s per loop

In [180]: %timeit { x : [] for x in set([i[0] for i in data_new])}
1 loops, best of 3: 13.6 s per loop

2 个答案:

答案 0 :(得分:4)

构建一个更大的数据集,然后是timeit:

<强>代码:

import random
data = [ [random.randint(1, 9) for _ in range(3)] for _ in range(1000000)]

<强>时序:

%timeit { x : [] for x in set([i[0] for i in data])}
# 10 loops, best of 3: 94.6 ms per loop
%timeit { i[0] : [] for i in data}
# 10 loops, best of 3: 106 ms per loop
%timeit { x: [] for x in set(i[0] for i in data)}
# 10 loops, best of 3: 114 ms per loop
%timeit { x: [] for x in {i[0] for i in data}}
# 10 loops, best of 3: 77.7 ms per loop

<强>原理

首先限制可用密钥空间意味着字典只需要为9个新列表分配(给定上面的randint)9个唯一密钥。当使用dict comp时,字典必须重复创建并将其键的值重新分配给新创建的列表......不同之处在于废弃空列表的重新分配(作为垃圾)已收集)以及创建空列表所花费的时间。

鉴于来自randint的统一分布,那么在一组1,000,000个元素中,有9个唯一值的空列表有111,111个分配和解除分配 - 这远远超过9个。

答案 1 :(得分:2)

这取决于您期望的重复次数。在较短的代码中,为输入列表中的每个项目创建空列表,这非常昂贵。使用静态值,越短越快。

以下是L = [[1,3,4], [3,5,2], [1,5,2]] * 100000

In [1]: %timeit { x : [] for x in {i[0] for i in L]}}
10 loops, best of 3: 58.9 ms per loop

In [2]: %timeit { i[0] : [] for i in L}
10 loops, best of 3: 68.1 ms per loop

现在使用常量None值进行测试:

In [3]: %timeit { x : None for x in set([i[0] for i in L])}
10 loops, best of 3: 59 ms per loop

In [4]: %timeit { i[0] : None for i in L}
10 loops, best of 3: 54.3 ms per loop

因此,不必要的列表创建使较短的列表执行缓慢,而使用常量值则更快。


我没有Python 2的ipython,我有点懒,但你要注意Python 2.7支持 set comprehensions ,至少在Python 3.4上要快得多而不是从列表创建集:

In [7]: %timeit { x : [] for x in {i[0] for i in L}}
10 loops, best of 3: 48.9 ms per loop
相关问题