我需要从给定的列表中选择一些元素,知道它们的索引。假设我想创建一个新列表,其中包含从给定列表[- 2,1,5,3,8,5,6]中索引为1,2,5的元素。我所做的是:

a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]

有什么更好的办法吗?比如c = a[b] ?


当前回答

有点像python的方式:

c = [x for x in a if a.index(x) in b]

其他回答

选择:

>>> map(a.__getitem__, b)
[1, 5, 5]

>>> import operator
>>> operator.itemgetter(*b)(a)
(1, 5, 5)

你可以使用operator.itemgetter:

from operator import itemgetter 
a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
print(itemgetter(*b)(a))
# Result:
(1, 5, 5)

或者你可以使用numpy:

import numpy as np
a = np.array([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
print(list(a[b]))
# Result:
[1, 5, 5]

但说真的,你现在的解决方案很好。这可能是其中最简洁的一个。

我的回答没有使用numpy或python集合。

查找元素的一种简单方法如下:

a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
c = [i for i in a if i in b]

缺点:此方法可能不适用于较大的列表。对于较大的列表,建议使用numpy。

基本的和不太广泛的测试,比较五个答案的执行时间:

def numpyIndexValues(a, b):
    na = np.array(a)
    nb = np.array(b)
    out = list(na[nb])
    return out

def mapIndexValues(a, b):
    out = map(a.__getitem__, b)
    return list(out)

def getIndexValues(a, b):
    out = operator.itemgetter(*b)(a)
    return out

def pythonLoopOverlap(a, b):
    c = [ a[i] for i in b]
    return c

multipleListItemValues = lambda searchList, ind: [searchList[i] for i in ind]

使用以下输入:

a = range(0, 10000000)
b = range(500, 500000)

简单的python循环是最快的,lambda操作紧随其后,mapIndexValues和getIndexValues始终非常相似,numpy方法在将列表转换为numpy数组后明显更慢。如果数据已经在numpy数组中,则使用numpy. numpyIndexValues方法。删除数组转换是最快的。

numpyIndexValues -> time:1.38940598 (when converted the lists to numpy arrays)
numpyIndexValues -> time:0.0193445 (using numpy array instead of python list as input, and conversion code removed)
mapIndexValues -> time:0.06477512099999999
getIndexValues -> time:0.06391049500000001
multipleListItemValues -> time:0.043773591
pythonLoopOverlap -> time:0.043021754999999995

我相信这已经被考虑过了:如果b中的指标数量很小并且是常数,我们可以这样写结果:

c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]]

或者更简单,如果索引本身是常量……

c = [a[1]] + [a[2]] + [a[5]]

或者如果有一个连续的索引范围…

c = a[1:3] + [a[5]]