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