Comment obtenir la position d'un article dans une liste?

169

J'itère une liste et je souhaite imprimer l'index de l'élément s'il remplit une certaine condition. Comment ferais-je cela?

Exemple:

testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
    if item == 1:
        print position
Sean
la source

Réponses:

280

Hmmm. Il y avait une réponse avec une compréhension de liste ici, mais elle a disparu.

Ici:

 [i for i,x in enumerate(testlist) if x == 1]

Exemple:

>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]

Mettre à jour:

D'accord, vous voulez une expression de générateur, nous aurons une expression de générateur. Voici à nouveau la compréhension de la liste, dans une boucle for:

>>> for i in [i for i,x in enumerate(testlist) if x == 1]:
...     print i
... 
0
5
7

Maintenant, nous allons construire un générateur ...

>>> (i for i,x in enumerate(testlist) if x == 1)
<generator object at 0x6b508>
>>> for i in (i for i,x in enumerate(testlist) if x == 1):
...     print i
... 
0
5
7

et assez facilement, nous pouvons attribuer cela à une variable, et l'utiliser à partir de là ...

>>> gen = (i for i,x in enumerate(testlist) if x == 1)
>>> for i in gen: print i
... 
0
5
7

Et dire que j'écrivais FORTRAN.

Charlie Martin
la source
6
Après probablement 25 ans de remise en question de la programmation fonctionnelle, je pense avoir enfin compris. la compréhension de la liste est une bombe.
Charlie Martin
15
Je suppose que vous voulez dire "une seule lettre" et franchement, un nom plus long dans cet exemple n'aurait plus de contenu informatif.
Charlie Martin
2
Merci pour une excellente réponse. Je pense que le commentaire de @ nailer pourrait concerner le fait que vous utilisez «i» dans deux contextes différents sur une seule ligne dans l'exemple du générateur; l'un à l'intérieur de la compréhension, et l'autre pour l'itérer. Je sais que ça m'a bouleversé une seconde.
Brown
1
@CharlieMartin Vous utilisez «i» pour l'index plutôt que l'élément selon la seule convention commune pour les variables à un seul caractère. Nommer l'index «index» et l'élément «item» éliminerait toute ambiguïté. De plus, vous répondez à un parent qui a utilisé «élément» et «position» et il est judicieux de ne pas renommer inutilement des parties du code d'origine dans votre réponse.
mikemaccana
1
Super syntaxe: o) Vous pouvez facilement obtenir un paramètre de ligne de commande. Qu'il y est un tableau d'arguments: args = ['x', '-p1', 'v1', '-p2', 'v2']. Puis la commande args[[i for i, x in enumerate(args) if x == '-p1'][0] + 1]revient'v1'
Theodor Keinstein
170

Qu'en est-il de ce qui suit?

print testlist.index(element)

Si vous n'êtes pas sûr que l'élément à rechercher se trouve réellement dans la liste, vous pouvez ajouter une vérification préliminaire, comme

if element in testlist:
    print testlist.index(element)

ou

print(testlist.index(element) if element in testlist else None)

ou la "voie pythonique", que je n'aime pas tant car le code est moins clair, mais parfois plus efficace,

try:
    print testlist.index(element)
except ValueError:
    pass
mmj
la source
5
au lieu de tester avant d'accéder, vous pouvez également simplement essayer de vérifierValueError
kratenko
Je pense qu'il veut pour trouver toutes les occurrences, vous semblez ne donner que la première.
tfv
@tfv Je ne vois pas comment vous pouvez arriver à une telle conclusion puisque la question dit "item" et non "items".
mmj
40

Utilisez enumerate:

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position
zdan
la source
10
for i in xrange(len(testlist)):
  if testlist[i] == 1:
    print i

xrange au lieu de range comme demandé (voir les commentaires).

jakber
la source
remplacez range () par xrange () - range () crée une liste, xrange () crée un itérateur. xrange () utilise moins de mémoire et l'appel initial est plus rapide.
gnud
2
Je suis d'accord pour les grandes listes dans les programmes python 2. Notez que 'range' fonctionnera toujours en python 3 (et fonctionnera comme xrange IIRC). «xrange» suit la voie des dinosaures.
jakber
2
Mise à jour: xrangeest supprimée dans Python 3.x, car le nouveau rangeest l'ancienxrange
tim-oh
5

Voici une autre façon de procéder:

try:
   id = testlist.index('1')
   print testlist[id]
except ValueError:
   print "Not Found"
Phil Rankin
la source
3
[x for x in range(len(testlist)) if testlist[x]==1]
user1713952
la source
2

Essayez ce qui suit:

testlist = [1,2,3,5,3,1,2,1,6]    
position=0
for i in testlist:
   if i == 1:
      print(position)
   position=position+1
B Prashantkumar
la source
1

Si votre liste devenait suffisamment volumineuse et que vous ne vous attendiez à trouver la valeur que dans un nombre restreint d'indices, considérez que ce code pourrait s'exécuter beaucoup plus rapidement car vous n'avez pas à itérer chaque valeur de la liste.

lookingFor = 1
i = 0
index = 0
try:
  while i < len(testlist):
    index = testlist.index(lookingFor,i)
    i = index + 1
    print index
except ValueError: #testlist.index() cannot find lookingFor
  pass

Si vous vous attendez à trouver beaucoup la valeur, vous devriez probablement simplement ajouter «index» à une liste et imprimer la liste à la fin pour gagner du temps par itération.


la source
J'ai fait quelques tests de chronométrage. La technique de compréhension de liste est 38% plus rapide que ce code. (J'ai remplacé votre déclaration d'impression par un appel outputlist.append)
Deestan
J'ai également fait des tests avec des tailles de liste de 100 000 valeurs aléatoires entre 1 et 100. Le code que j'ai écrit était dans certains cas deux fois plus rapide. Aucun test de temps n'est comparable à l'application de l'affiche (ils doivent se tester pour être sûrs, bien sûr). Je m'excuse si mon opinion a été préjudiciable à ce message.
0

Je pense qu'il pourrait être utile d'utiliser la méthode curselection () de la bibliothèque Tkinter:

from Tkinter import * 
listbox.curselection()

Cette méthode fonctionne sur les widgets de listbox Tkinter, vous devrez donc en construire un au lieu d'une liste.

Cela renverra une position comme celle-ci:

('0',) (bien que les versions ultérieures de Tkinter puissent renvoyer une liste d'entiers à la place)

Ce qui est pour la première position et le nombre changera en fonction de la position de l'élément.

Pour plus d'informations, consultez cette page: http://effbot.org/tkinterbook/listbox.htm

Salutations.

xXAngelJinXx
la source
1
Idée intéressante. Comme cela nécessite d'importer la bibliothèque Tkinter entière, ce n'est pas le moyen le plus efficace de résoudre le problème.
seaotternerd
3
C'est un chemin tellement inefficace et sinueux que je dirais que c'est une mauvaise réponse, même si cela répond un peu à la question.
Cette réponse n'a rien à voir avec la question.
Cody Piersall
0

Pourquoi compliquer les choses?

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position
Abhishek
la source
0

Juste pour illustrer un exemple complet avec le input_listqui a searies1(exemple: input_list [0]) dans lequel vous voulez faire une recherche de series2(exemple: input_list [1]) et obtenir les index de series2 s'il existe dans series1.

Remarque: votre certain conditionira dans l'expression lambda si les conditions sont simples

input_list = [[1,2,3,4,5,6,7],[1,3,7]]
series1 = input_list[0]
series2 = input_list[1]
idx_list = list(map(lambda item: series1.index(item) if item in series1 else None, series2))
print(idx_list)

production:

[0, 2, 6]
ravibeli
la source
-2
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
    if id == 1:
        print testlist[id]

Je suppose que c'est exactement ce que vous voulez. ;-) 'id' sera toujours l'index des valeurs de la liste.

Léonard
la source