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

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

我需要从给定列表中选择一些元素,知道它们的索引。假设我要创建一个新列表,该列表包含给定列表[-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]一样?

I need to choose some elements from the given list, knowing their index. Let say I would like to create a new list, which contains element with index 1, 2, 5, from given list [-2, 1, 5, 3, 8, 5, 6]. What I did is:

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

Is there any better way to do it? something like c = a[b] ?


回答 0

您可以使用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]

但实际上,您当前的解决方案很好。这可能是所有人中最整洁的。

You can use 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)

Or you can use 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]

But really, your current solution is fine. It’s probably the neatest out of all of them.


回答 1

备择方案:

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

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

Alternatives:

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

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

回答 2

另一个解决方案可以通过pandas Series:

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)

Another solution could be via pandas Series:

import pandas as pd

a = pd.Series([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
c = a[b]

You can then convert c back to a list if you want:

c = list(c)

回答 3

比较五个提供的答案的执行时间的基础测试,但不是非常广泛的测试:

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数组后速度显着降低。最快的。

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

Basic and not very extensive testing comparing the execution time of the five supplied answers:

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]

using the following input:

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

simple python loop was the quickest with lambda operation a close second, mapIndexValues and getIndexValues were consistently pretty similar with numpy method significantly slower after converting lists to numpy arrays.If data is already in numpy arrays the numpyIndexValues method with the numpy.array conversion removed is quickest.

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

回答 4

我确定已经考虑了这一点:如果b中的索引数量很小且恒定,则可以将结果写为:

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

如果索引本身是常数,甚至更简单…

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

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

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

I’m sure this has already been considered: If the amount of indices in b is small and constant, one could just write the result like:

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

Or even simpler if the indices itself are constants…

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

Or if there is a consecutive range of indices…

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

回答 5

这是一个更简单的方法:

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

Here’s a simpler way:

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

回答 6

我的答案不使用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。

My answer does not use numpy or python collections.

One trivial way to find elements would be as follows:

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

Drawback: This method may not work for larger lists. Using numpy is recommended for larger lists.


回答 7

静态索引和小清单?

不要忘记,如果列表很小并且索引没有更改,例如在您的示例中,有时最好的方法是使用序列解压缩

_,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

Static indexes and small list?

Don’t forget that if the list is small and the indexes don’t change, as in your example, sometimes the best thing is to use sequence unpacking:

_,a1,a2,_,_,a3,_ = a

The performance is much better and you can also save one line of code:

 %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

回答 8

一种pythonic方式:

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

Kind of pythonic way:

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