Доступ к нескольким элементам списка, зная их индекс

Мне нужно выбрать некоторые элементы из данного списка, зная их индекс. Предположим, что я хотел бы создать новый список, содержащий элемент с индексом 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]?

Ответ 1

Вы можете использовать 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]

Но на самом деле ваше текущее решение в порядке. Это, наверное, самое из всех из них.

Ответ 2

Альтернатива:

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

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

Ответ 3

Другим решением может быть pandas Серия:

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)

Ответ 4

Базовое и не очень обширное тестирование, сравнивающее время выполнения пяти предоставленных ответов:

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 был самым быстрым, когда операция лямбда была близкой секундой, mapIndexValues ​​и getIndexValues ​​были последовательно похожи на метод numpy значительно медленнее после преобразования списков в массивы numpy. Если данные уже находятся в массивах numpy, метод numpyIndexValues ​​с numpy.array конверсия удалена быстрее.

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

Ответ 5

Я уверен, что это уже было рассмотрено: если количество индексов в b невелико и постоянное, можно просто написать результат, например:

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

Или даже проще, если сами индексы являются константами...

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

Или, если имеется ряд индексов подряд...

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

Ответ 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 рекомендуется для больших списков.

Ответ 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

Ответ 8

Здесь более простой способ:

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