考虑两个列表:
a = [2, 4, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我想要一个结果列表 c where
c = [0, 0, 2, 0, 4, 5, 0 ,0 ,0 ,0]
是一个长度为 len(b) 的列表,其值取自 b,由 a 中指定的索引定义,其他地方为零。
这样做最优雅的方法是什么?
请您参考如下方法:
使用 list comprehension与 conditional expression和 enumerate .
此 LC 将遍历列表 b 的索引和值,如果在 a 中找到索引 i 则它将将元素设置为 v,否则它将设置为 0。
a = [2, 4, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = [v if i in a else 0 for i, v in enumerate(b)]
print(c)
# [0, 0, 2, 0, 4, 5, 0, 0, 0, 0]
注意:如果 a 很大,那么在使用 in 之前最好先转换为一个集合。 time complexity将 in 与列表一起使用是 O(n),而对于集合,它是 O(1)(在两者的平均情况下)。
list comprehension大致等价于如下代码(解释):
c = []
for i, v in enumerate(b):
if i in a:
c.append(v)
else:
c.append(0)
因为您可以选择使用 numpy,所以我在下面提供了一个简单的方法,它使用初始化一个用零填充的数组,然后使用列表索引来替换元素。
import numpy as np
a2 = np.array(a)
b2 = np.array(b)
c = np.zeros(len(b2))
c[a2] = b[a2]
当对三种方法(我的 list comp、我的 numpy 和 Jon 的方法)计时时,N = 1000 的结果如下,a = list(range(0, N, 10)),和 b = list(range(N))。
In [170]: %timeit lc_func(a,b)
100 loops, best of 3: 3.56 ms per loop
In [171]: %timeit numpy_func(a2,b2)
100000 loops, best of 3: 14.8 µs per loop
In [172]: %timeit jon_func(a,b)
10000 loops, best of 3: 22.8 µs per loop
这是意料之中的。 numpy 函数最快,但 Jon 的函数和 numpy 都比列表理解快得多。如果我将元素的数量增加到 100,000,那么 numpy 和 Jon 的方法之间的差距会变得更大。
有趣的是,对于小 N Jon 的函数是最好的!我怀疑这是因为创建 numpy 数组的开销被列表的开销压倒了.
故事的寓意:大N?和 numpy 一起去吧。小N?和乔恩一起去。
