Python 访问列表的多个元素,知道它们的索引

Python 访问列表的多个元素,知道它们的索引,python,python-3.x,list,indexing,element,Python,Python 3.x,List,Indexing,Element,我需要从给定的列表中选择一些元素,知道它们的索引。假设我想创建一个新的列表,其中包含一个元素,该元素的索引为1,2,5,来自给定的列表[-2,1,5,3,8,5,6]。我所做的是: a = [-2,1,5,3,8,5,6] b = [1,2,5] c = [ a[i] for i in b] 有没有更好的办法?类似于c=a[b]?备选方案: >>> map(a.__getitem__, b) [1, 5, 5] 您可以使用: 或者您可以使用: 但实际上,您当前的解决方案

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

a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]
有没有更好的办法?类似于c=a[b]?

备选方案:

>>> map(a.__getitem__, b)
[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.array转换的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]]

另一种解决方案是通过熊猫系列:

import pandas as pd

a = pd.Series([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
c = a[b]
如果需要,可以将c转换回列表:

c = list(c)
静态索引和小列表? 不要忘记,如果列表很小,并且索引没有改变,例如在您的示例中,有时最好使用:

性能更好,您还可以保存一行代码:

 %timeit _,a1,b1,_,_,c1,_ = a
10000000 loops, best of 3: 154 ns per loop 
%timeit itemgetter(*b)(a)
1000000 loops, best of 3: 753 ns per loop
 %timeit [ a[i] for i in b]
1000000 loops, best of 3: 777 ns per loop
 %timeit map(a.__getitem__, b)
1000000 loops, best of 3: 1.42 µs per loop
这里有一个更简单的方法:

a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [e for i, e in enumerate(a) if i in b]
一种类似于蟒蛇的方式:

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


+我要说的是,
c=[a[i]代表b中的i]
非常好。请注意,如果b的元素少于2个,则
itemgetter
解决方案将不会执行相同的操作。旁注:在多进程中使用itemgetter不起作用。Numpy在多进程中工作得非常好。附加注释,
a[b]
仅在
a
是Numpy数组时工作,即使用Numpy函数创建数组。我已经对非Numpy选项进行了基准测试,itemgetter似乎是最快的,甚至比简单地在括号内键入所需索引还要快一点,使用Python3。44@citizen2077,你能举一个你描述的语法的例子吗?顺便说一下,我在这里找到了另一个解决方案。我还没有测试它,但我想一旦你感兴趣,我可以将它发布在这里,这是与问题中提到的相同的解决方案,但包装在
lambda
函数中。可能重复不需要迭代
a
[a[i]表示b中的i]
此方法在任何其他情况下都不起作用。如果
a
中还有另外5个怎么办?我想,如果你担心索引器,那么可以更快地进行这种交集如果b的数字超过a的大小,请尝试
[a[i]如果我不知道您使用的Python解释器是什么,但是第一种方法
numpyIndexValues
不起作用,因为
a
b
属于
range
类型。我猜您需要先将
a
b
转换为
numpy.ndarrays
。@strpeter是的,我不是在比较苹果,我已经在测试用例中为numpyIndexValues创建了numpy数组作为输入。我现在已经解决了这个问题,并且都使用相同的列表作为输入。感谢您提醒我,
[a]+[b]=[a,b]
请注意,
+
会复制列表。您可能希望
扩展
而不是修改列表。第一个问题是
\uuu getitem\uuuuuuuuuuu
似乎不可比较,例如如何映射项目的类型?
映射(类型(a.\uu getitem\uuuuuuuuuuuuuuu),b)
@alancalvitti,
lambda x:type在这种情况下,使用
[…]
更为紧凑:
lambda x:type(a[x]),b
只需转换回一个列表:
list(map(a..\uu getitem\uuuux,b))
我想说这比OP的示例更不“pythonic”——你已经设法将他们的
O(n)
解决方案转换成了
O(n^2)
解决方案,同时几乎将代码长度增加一倍。您还需要注意,如果列表包含模糊或部分相等的对象,则该方法将失败,例如,如果
a
包含
浮点('nan')
,则始终会引发
值错误。
_,a1,a2,_,_,a3,_ = a
 %timeit _,a1,b1,_,_,c1,_ = a
10000000 loops, best of 3: 154 ns per loop 
%timeit itemgetter(*b)(a)
1000000 loops, best of 3: 753 ns per loop
 %timeit [ a[i] for i in b]
1000000 loops, best of 3: 777 ns per loop
 %timeit map(a.__getitem__, b)
1000000 loops, best of 3: 1.42 µs per loop
a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [e for i, e in enumerate(a) if i in b]
c = [x for x in a if a.index(x) in b]