使用第三个列表中指定的索引处的另一个列表中的项创建列表

时间:2014-12-05 09:56:21

标签: python

考虑两个清单:

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>}。

这样做最优雅的方式是什么?

2 个答案:

答案 0 :(得分:8)

list comprehensionconditional 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 = 1000a = 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]