Obtenir une sous-liste d'une liste Python, avec les indices donnés?
J'ai une liste Python, dire a = [0,1,2,3,4,5,6]. J'ai aussi une liste d'indices, de dire b = [0,2,4,5]. Comment puis-je obtenir la liste des éléments de a avec des indices en b?
Vous pouvez utiliser compréhension de liste pour obtenir cette liste:
c =[a[index]for index in b]print c
Ceci est équivalent à:
c=[]for index in b:
c.append(a[index])print c
De sortie:
[0,2,4,5]
Remarque:
Rappelez-vous que some_list[index] est la notation utilisée pour accéder à un élément d'un list dans un index spécifique.
17
Quelque chose de différent...
>>> a = range(7)>>> b =[0,2,4,5]>>>import operator
>>> operator.itemgetter(*b)(a)(0,2,4,5)
La itemgetter fonction prend une ou plusieurs clés comme arguments et retourne une fonction qui permet de renvoyer les articles à la donné les clés dans son argument. Donc, dans ce qui précède, nous créons une fonction qui permet de renvoyer les articles à l'indice 0, indice 2, indice 4, et de l'indice 5, puis d'appliquer cette fonction à a.
Il semble être un peu plus rapide que l'équivalent compréhension de liste
In[1]:import operator
In[2]: a = range(7)In[3]: b =[0,2,4,5]In[4]:%timeit operator.itemgetter(*b)(a)1000000 loops, best of 3:388 ns per loop
In[5]:%timeit [ a[i]for i in b ]1000000 loops, best of 3:415 ns per loop
In[6]: f = operator.itemgetter(*b)In[7]:%timeit f(a)10000000 loops, best of 3:183 ns per loop
Comme pour pourquoi itemgetter est plus rapide, la compréhension est d'exécuter du Python octets de codes.
Python2.7.11|Anaconda2.4.1(64-bit)|(default,Jan192016,12:08:31)[MSC v.150064 bit (AMD64)] on win32
In[2]:import numpy.random as nprnd
idx = nprnd.randint(1000, size=10000)
l = nprnd.rand(1000).tolist()from operator import itemgetter
import operator
f = operator.itemgetter(*idx)%timeit f(l)%timeit list(itemgetter(*idx)(l))%timeit [l[_]for _ in idx]# list comprehension%timeit map(l.__getitem__, idx)%timeit list(l[_]for _ in idx)# a generator expression passed to a list constructor.%timeit map(lambda _: l[_], idx)# using 'map'%timeit [x for i, x in enumerate(l)if i in idx]%timeit filter(lambda x: l.index(x)in idx, l)# UPDATE @Kundor: work only for list with unique elements10000 loops, best of 3:175µs per loop
1000 loops, best of 3:707µs per loop
1000 loops, best of 3:978µs per loop
1000 loops, best of 3:1.03 ms per loop
1000 loops, best of 3:1.18 ms per loop
1000 loops, best of 3:1.86 ms per loop
100 loops, best of 3:12.3 ms per loop
10 loops, best of 3:21.2 ms per loop
De sorte que le plus rapide est f = operator.itemgetter(*idx); f(l)
>>> a =[0,10,20,30,40,50,60]>>> b =[0,2,4,5]>>> li =[a[i]for i in b]>>> li
[0,20,40,50]
1
La plupart des solutions proposées produira un KeyError si b contient un index n'est pas présent dans a. L'exemple suivant permet de sauter invalide indices si cela est souhaité.
>>> b =[0,2,4,5]>>> a =[0,1,2,3,4,5,6]>>>[x for i,x in enumerate(a)if i in b][0,2,4,5]>>> b =[0,2,4,500]>>>[x for i,x in enumerate(a)if i in b][0,2,4]
enumerate produit des n-uplets de l'indice,la valeur des paires. Puisque nous avons à la fois l'élément et son index, on peut vérifier la présence de l'indice b
1
Encore une autre solution pour améliorer les performances, si cela est important pour vous - c'est pas le plus Pythonic mais je suis assez sûr que c'est la plus efficace:
Remarque: Vous n'avez pas besoin de convertir un list en Python 2. Cependant, vous n'en Python 3 la suite (si tous les futurs visiteurs peuvent avoir un problème similaire).
1
À l'aide de numpy.asarray. Numpy permet d'obtenir subarray de tableau en liste d'indices.
>>>import numpy as np
>>> a =[0,10,20,30,40,50,60]>>> b =[0,2,4,5]>>> res = np.asarray(a)[b].tolist()>>> res
[0,20,40,50]
Vous pouvez utiliser compréhension de liste pour obtenir cette liste:
Ceci est équivalent à:
De sortie:
Remarque:
Rappelez-vous que
some_list[index]
est la notation utilisée pour accéder à un élément d'unlist
dans un index spécifique.Quelque chose de différent...
La
itemgetter
fonction prend une ou plusieurs clés comme arguments et retourne une fonction qui permet de renvoyer les articles à la donné les clés dans son argument. Donc, dans ce qui précède, nous créons une fonction qui permet de renvoyer les articles à l'indice 0, indice 2, indice 4, et de l'indice 5, puis d'appliquer cette fonction àa
.Il semble être un peu plus rapide que l'équivalent compréhension de liste
Comme pour pourquoi
itemgetter
est plus rapide, la compréhension est d'exécuter du Python octets de codes.Tout
itemgetter
est un seul appel mis en œuvre dans C:Si vous êtes un fan de programmation fonctionnellevous pouvez utiliser
map
etde la liste.__getitem__
:La compréhension de liste approche est plus canonique en Python...
Un peu de la comparaison de la vitesse pour tous les moyens mentionnés et d'autres de Python dictionnaire: Obtenir la liste des valeurs pour la liste des clés:
De sorte que le plus rapide est
f = operator.itemgetter(*idx); f(l)
À l'aide de Compréhension De Liste ,cela devrait fonctionner -
De tester ce -
La plupart des solutions proposées produira un
KeyError
sib
contient un index n'est pas présent dansa
. L'exemple suivant permet de sauter invalide indices si cela est souhaité.enumerate
produit des n-uplets de l'indice,la valeur des paires. Puisque nous avons à la fois l'élément et son index, on peut vérifier la présence de l'indice bEncore une autre solution pour améliorer les performances, si cela est important pour vous - c'est pas le plus Pythonic mais je suis assez sûr que c'est la plus efficace:
Remarque: Vous n'avez pas besoin de convertir un
list
en Python 2. Cependant, vous n'en Python 3 la suite (si tous les futurs visiteurs peuvent avoir un problème similaire).À l'aide de
numpy.asarray
. Numpy permet d'obtenir subarray de tableau en liste d'indices.