index()
donnera juste la première occurrence d'un élément dans une liste. Existe-t-il une astuce intéressante qui renvoie tous les indices d'une liste?
index()
donnera juste la première occurrence d'un élément dans une liste. Existe-t-il une astuce intéressante qui renvoie tous les indices d'une liste?
Réponses:
Vous pouvez utiliser une liste de compréhension:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumerate
à 2.3. Alors oui, si votre Python est ancien, utilisez filter()
.
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])
renvoie []
au lieu de [[0, 1], [0, 0], [1, 1]]
.
(a == 1).nonzero()
pour un tableau NumPy a
.
Bien que ce ne soit pas une solution pour les listes directement, numpy
brille vraiment pour ce genre de chose:
import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]
Retour:
ii ==>array([2, 8])
Cela peut être beaucoup plus rapide pour les listes (tableaux) avec un grand nombre d'éléments par rapport à certaines des autres solutions.
[0]
est nécessaire car where
retourne un tuple(array([2, 8], dtype=int64),)
all_id_resp_address
ne devrait tout d'abord np.array
pas l' être list
.
list
et str
, évidemment, vous êtes passé False
à np.where
. Lorsque vous comparez np.array
avec smth. vous obtenez un tableau de valeurs booléennes. Trouve ensuite les np.where
positions de toutes les True
valeurs de ce tableau.
Une solution utilisant list.index
:
def indices(lst, element):
result = []
offset = -1
while True:
try:
offset = lst.index(element, offset+1)
except ValueError:
return result
result.append(offset)
C'est beaucoup plus rapide que la compréhension de liste avec enumerate
, pour les grandes listes. Il est également beaucoup plus lent que la numpy
solution si vous disposez déjà de la matrice, sinon le coût de conversion l'emporte sur le gain de vitesse (testé sur des listes entières avec 100, 1000 et 10000 éléments).
REMARQUE: une note de prudence basée sur le commentaire de Chris_Rands: cette solution est plus rapide que la compréhension de la liste si les résultats sont suffisamment clairsemés, mais si la liste contient de nombreuses instances de l'élément recherché (plus de ~ 15% de la liste , sur un test avec une liste de 1000 entiers), la compréhension de la liste est plus rapide.
timeit.timeit
avec des listes générées aléatoirement. C'est un point important cependant, et je suppose que c'est peut-être pourquoi vous posez la question. À l'époque, cela ne m'est pas venu à l'esprit, mais les gains de vitesse ne sont vrais que si les résultats sont suffisamment clairsemés. Je viens de tester avec une liste pleine d'éléments à rechercher, et c'est beaucoup plus lent que la compréhension de la liste.
more_itertools.locate
recherche des indices pour tous les éléments qui remplissent une condition.
from more_itertools import locate
list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]
list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]
more_itertools
est une bibliothèque tierce > pip install more_itertools
.
conda install
soit devenue très instable récemment)
Une autre solution (désolé si les doublons) pour toutes les occurrences:
values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)
Ou utilisez range
(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Pour (python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
Et puis (dans les deux cas):
print(l)
Est comme prévu.
Utilisation de filter () en python2.
>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]
Vous pouvez créer un dicton par défaut
from collections import defaultdict
d1 = defaultdict(int) # defaults to 0 values for keys
unq = set(lst1) # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
d1[each] = lst1.count(each)
else:
print(d1)
Avec enumerate (alist), vous pouvez stocker le premier élément (n) qui est l'index de la liste lorsque l'élément x est égal à ce que vous recherchez.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Cette fonction prend l'élément et la liste comme arguments et renvoie la position de l'élément dans la liste, comme nous l'avons vu précédemment.
def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]
print(indexlist("1", "010101010"))
Production
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Production:
0
4
for-loop
:enumerate
et une compréhension de liste sont plus efficaces et pythoniques, cependant, cette réponse s'adresse aux étudiants qui peuvent ne pas être autorisés à utiliser certaines de ces fonctions intégrées .indices
for i in range(len(x)):
, qui itère essentiellement à travers une liste d'emplacements d'index[0, 1, 2, 3, ..., len(x)-1]
i
où, oùx[i]
correspond à value
, àindices
def get_indices(x: list, value: int) -> list:
indices = list()
for i in range(len(x)):
if x[i] == value:
indices.append(i)
return indices
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indices
,, sont implémentées avec des indications de type . Dans ce cas, la liste n
, est un tas deint
s, donc nous recherchons value
, également défini comme un int
.while-loop
et .index
:.index
, utilisez try-except
pour la gestion des erreurs car un ValueError
se produira s'il value
ne figure pas dans la liste.def get_indices(x: list, value: int) -> list:
indices = list()
i = 0
while True:
try:
# find an occurrence of value and update i to that index
i = x.index(value, i)
# add i to the list
indices.append(i)
# advance i by 1
i += 1
except ValueError as e:
break
return indices
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indeices
est un peu plus rapide (~ 15%) que la compréhension de liste normale. J'essaie de comprendre.
Si vous utilisez Python 2, vous pouvez obtenir les mêmes fonctionnalités avec ceci:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Où se my_list
trouve la liste dont vous souhaitez obtenir les index et value
la valeur recherchée. Usage:
f(some_list, some_element)
Si vous devez rechercher toutes les positions des éléments entre certains indices , vous pouvez les indiquer:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]