用列表列表中的第一个元素制作字典
make a dictionary out of first elements in a list of list
这是一个关于使用 set() on list comprehension inside dictionary comprehension Vs dictionary comprehension and repeated assignment to a new dictionary
的性能问题
所以我碰巧有一个数据集,它是一个列表列表,我需要在大列表中的每个列表中获得一个索引为“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
这取决于您期望的重复次数。在较短的代码中,为输入列表中的每个项目创建一个空列表,这非常昂贵。使用静态值,越短越快
下面,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
因此,不必要的列表创建会使较短的列表执行缓慢,而使用常量值绝对更快。
我没有 ipython 用于 Python 2,我有点懒惰,但你会想注意到 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
构建更大的数据集,然后计时:
代码:
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
理由:
限制可用键space首先意味着字典只需分配(给定上面的randint
)9个唯一键给9个新列表。使用 dict comp 时,字典必须重复创建并将其键的值重新分配给 newly created 列表...不同之处在于释放空列表的开销(被垃圾收集)和创建 new 空列表所花费的时间。
给定来自 randint
的均匀分布,那么在一组 1,000,000 个元素中有 9 个唯一值的空列表的 111,111 次分配和取消分配 - 这比仅仅 9 个要多得多。
这是一个关于使用 set() on list comprehension inside dictionary comprehension Vs dictionary comprehension and repeated assignment to a new dictionary
的性能问题所以我碰巧有一个数据集,它是一个列表列表,我需要在大列表中的每个列表中获得一个索引为“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
这取决于您期望的重复次数。在较短的代码中,为输入列表中的每个项目创建一个空列表,这非常昂贵。使用静态值,越短越快
下面,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
因此,不必要的列表创建会使较短的列表执行缓慢,而使用常量值绝对更快。
我没有 ipython 用于 Python 2,我有点懒惰,但你会想注意到 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
构建更大的数据集,然后计时:
代码:
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
理由:
限制可用键space首先意味着字典只需分配(给定上面的randint
)9个唯一键给9个新列表。使用 dict comp 时,字典必须重复创建并将其键的值重新分配给 newly created 列表...不同之处在于释放空列表的开销(被垃圾收集)和创建 new 空列表所花费的时间。
给定来自 randint
的均匀分布,那么在一组 1,000,000 个元素中有 9 个唯一值的空列表的 111,111 次分配和取消分配 - 这比仅仅 9 个要多得多。