Je dois choisir des éléments dans la liste donnée, en connaissant leur index. Supposons que je souhaite créer une nouvelle liste, qui contient un élément d'indice 1, 2, 5, à partir de la liste donnée [-2, 1, 5, 3, 8, 5, 6]. Ce que j'ai fait c'est:
a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]
Y a-t-il une meilleure façon de le faire? quelque chose comme c = a [b]?
Vous pouvez utiliser 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)
_
Ou vous pouvez utiliser 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]
_
Mais vraiment, votre solution actuelle est satisfaisante. C'est probablement le plus intéressant de tous.
Alternatives:
>>> map(a.__getitem__, b)
[1, 5, 5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(1, 5, 5)
Une autre solution pourrait être via pandas Series:
import pandas as pd
a = pd.Series([-2, 1, 5, 3, 8, 5, 6])
b = [1, 2, 5]
c = a[b]
Vous pouvez ensuite reconvertir c en liste si vous voulez:
c = list(c)
Tests basiques et peu exhaustifs comparant le temps d'exécution des cinq réponses fournies:
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]
en utilisant l'entrée suivante:
a = range(0, 10000000)
b = range(500, 500000)
la boucle simple python était la plus rapide, l'opération lambda étant une seconde proche, mapIndexValues et getIndexValues étaient toujours assez similaires avec la méthode numpy nettement plus lente après la conversion des listes en tableaux numpy. La conversion numpy.array supprimée est la plus rapide.
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
Je suis sûr que cela a déjà été pris en compte: si la quantité d'indices dans b est petite et constante, on pourrait simplement écrire le résultat comme:
c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]]
Ou encore plus simple si les indices eux-mêmes sont des constantes ...
c = [a[1]] + [a[2]] + [a[5]]
Ou s'il y a une plage d'indices consécutive ...
c = a[1:3] + [a[5]]
Ma réponse n'utilise pas les collections numpy ou python.
Une façon triviale de trouver des éléments serait la suivante:
a = [-2, 1, 5, 3, 8, 5, 6]
b = [1, 2, 5]
c = [i for i in a if i in b]
Inconvénient: cette méthode peut ne pas fonctionner pour des listes plus volumineuses. L'utilisation de numpy est recommandée pour des listes plus volumineuses.
N'oubliez pas que si la liste est petite et que les index ne changent pas, comme dans votre exemple, la meilleure chose à faire est parfois d'utiliser décompression de séquence :
_,a1,a2,_,_,a3,_ = a
Les performances sont bien meilleures et vous pouvez également enregistrer une ligne de 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