考虑两个清单:
a = [2, 4, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我想要一个结果列表c
其中
c = [0, 0, 2, 0, 4, 5, 0 ,0 ,0 ,0]
是一个长度为len(b)
的列表,其值取自b
中由a
中指定的索引定义的值{/ p>}。
这样做最优雅的方式是什么?
答案 0 :(得分:8)
list comprehension和conditional expression使用enumerate
。
此LC将迭代索引和列表b
的值,如果在i
中找到索引a
,则它会将元素设置为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
之前,您可能最好先转换为设置。使用in
和列表的time complexity是O(n),而对于一个集合,它是O(1)(在两者的平均情况下)。
列表理解大致相当于以下代码(用于解释):
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]
在对三种方法(我的列表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?跟Jon一起去。
答案 1 :(得分:5)
另一种选择是使用0
预初始化目标列表 - 快速操作,然后将值覆盖到合适的索引,例如:
a = [2, 4, 5]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = [0] * len(b)
for el in a:
c[el] = b[el]
# [0, 0, 2, 0, 4, 5, 0, 0, 0, 0]