Je suis un peu confus par cette question: voulez-vous rechercher un élément récursivement à tous les niveaux d'une liste multidimensionnelle, ou voulez-vous uniquement rechercher des occurrences dans le niveau supérieur de la liste?
Anderson Green
22
À mon avis, il devrait y avoir une méthode de liste qui fait exactement cela.
Otocan
Réponses:
545
Vous pouvez utiliser une liste de compréhension:
indices =[i for i, x in enumerate(my_list)if x =="whatever"]
Sur les anciens pythons, utilisez filter () pour essentiellement les mêmes fonctionnalités.
Gleno
44
Les compréhensions de liste sont apparues en python à 2.0, enumerateà 2.3. Alors oui, si votre Python est ancien, utilisez filter().
Steven Rumbalski
2
Cette technique ne trouvera pas toutes les occurrences d'un élément dans un tableau multidimensionnel. Par exemple, print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])renvoie []au lieu de [[0, 1], [0, 0], [1, 1]].
Anderson Green
10
@AndersonGreen: Le terme "tableau multidimensionnel" suggère une structure de données qui est garantie d'avoir une taille uniforme le long de chacun de ses axes. Il n'y a pas une telle structure de données en Python simple. Il y a des listes de listes, mais elles sont très différentes des "tableaux multidimensionnels". Si vous voulez ce dernier, vous devriez envisager d'utiliser NumPy, qui vous permet de faire des choses comme (a == 1).nonzero()pour un tableau NumPy a.
Sven Marnach
2
@MadmanLee Si vous voulez quelque chose de rapide, utilisez NumPy. Voir la réponse de JoshAdel
Georgy
117
Bien que ce ne soit pas une solution pour les listes directement, numpybrille 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.
J'ai remarqué que le [0] à la fin convertit ce qui serait un tableau en chaîne. Je suis curieux de savoir pourquoi vous avez choisi de faire cela.
amelia
5
@amelia [0]est nécessaire car whereretourne un tuple(array([2, 8], dtype=int64),)
Winand
1
Hé @Winand, j'ai mis [0] mais j'ai toujours les deux parties. Voici mon code: (nrg.local_logs.all_id_resp_address est une liste) "ste =" 199.38.164.165 "value = np.where (nrg.local_logs.all_id_resp_address == ste) [0]" Je serai heureux si vous pouvez dire moi ce que j'ai fait de mal
Tomer
2
@Tomer all_id_resp_addressne devrait tout d'abord np.arraypas l' être list.
Winand
1
@Tomer vous avez essayé de comparer listet str, évidemment, vous êtes passé Falseà np.where. Lorsque vous comparez np.arrayavec smth. vous obtenez un tableau de valeurs booléennes. Trouve ensuite les np.wherepositions de toutes les Truevaleurs de ce tableau.
Winand
29
Une solution utilisant list.index:
def indices(lst, element):
result =[]
offset =-1whileTrue:try:
offset = lst.index(element, offset+1)exceptValueError: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 numpysolution 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.
Vous dites que c'est plus rapide qu'une liste de composition, pouvez-vous montrer vos horaires qui le démontrent?
Chris_Rands
5
C'était il y a longtemps, j'ai probablement utilisé timeit.timeitavec 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.
Paulo Almeida
18
Que diriez-vous:
In[1]: l=[1,2,3,4,3,2,5,6,7]In[2]:[i for i,val in enumerate(l)if val==3]Out[2]:[2,4]
Obtention de toutes les occurrences et de la position d'un ou plusieurs éléments (identiques) dans une liste
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]>>>
Faisons notre fonction findindex
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]
Facile
for n, i in enumerate([1,2,3,4,1]):if i ==1:print(n)
Cette réponse a été la plus simple à implémenter dans mon code existant.
Ryan Harris
2
Utilisation d'un for-loop:
Réponses avec 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 .
créer une liste vide, indices
créer la boucle avec for i in range(len(x)):, qui itère essentiellement à travers une liste d'emplacements d'index[0, 1, 2, 3, ..., len(x)-1]
dans la boucle, ajoutez n'importe ioù, 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]
Les fonctions 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.
Utilisant un while-loop et .index:
Avec .index, utilisez try-exceptpour la gestion des erreurs car un ValueErrorse produira s'il valuene figure pas dans la liste.
def get_indices(x: list, value: int)-> list:
indices = list()
i =0whileTrue: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 +=1exceptValueErroras e:breakreturn indices
print(get_indices(n,-60))>>>[4,8,9]
Réponses:
Vous pouvez utiliser une liste de compréhension:
la source
enumerate
à 2.3. Alors oui, si votre Python est ancien, utilisezfilter()
.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 NumPya
.Bien que ce ne soit pas une solution pour les listes directement,
numpy
brille vraiment pour ce genre de chose:Retour:
Cela peut être beaucoup plus rapide pour les listes (tableaux) avec un grand nombre d'éléments par rapport à certaines des autres solutions.
la source
[0]
est nécessaire carwhere
retourne un tuple(array([2, 8], dtype=int64),)
all_id_resp_address
ne devrait tout d'abordnp.array
pas l' êtrelist
.list
etstr
, évidemment, vous êtes passéFalse
ànp.where
. Lorsque vous compareznp.array
avec smth. vous obtenez un tableau de valeurs booléennes. Trouve ensuite lesnp.where
positions de toutes lesTrue
valeurs de ce tableau.Une solution utilisant
list.index
:C'est beaucoup plus rapide que la compréhension de liste avec
enumerate
, pour les grandes listes. Il est également beaucoup plus lent que lanumpy
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.
la source
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.Que diriez-vous:
la source
la source
more_itertools.locate
recherche des indices pour tous les éléments qui remplissent une condition.more_itertools
est une bibliothèque tierce> pip install more_itertools
.la source
conda install
soit devenue très instable récemment)Une autre solution (désolé si les doublons) pour toutes les occurrences:
la source
Ou utilisez
range
(python 3):Pour (python 2):
Et puis (dans les deux cas):
Est comme prévu.
la source
Utilisation de filter () en python2.
la source
Vous pouvez créer un dicton par défaut
la source
Obtention de toutes les occurrences et de la position d'un ou plusieurs éléments (identiques) dans une liste
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.
Faisons notre fonction findindex
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.
Production
Facile
Production:
la source
Utilisation d'un
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
x[i]
accède à la liste par indexget_indices
,, sont implémentées avec des indications de type . Dans ce cas, la listen
, est un tas deint
s, donc nous recherchonsvalue
, également défini comme unint
.Utilisant un
while-loop
et.index
:.index
, utiliseztry-except
pour la gestion des erreurs car unValueError
se produira s'ilvalue
ne figure pas dans la liste.la source
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:
Où se
my_list
trouve la liste dont vous souhaitez obtenir les index etvalue
la valeur recherchée. Usage:la source
Si vous devez rechercher toutes les positions des éléments entre certains indices , vous pouvez les indiquer:
la source