Question En Python, comment puis-je trouver l'index du premier élément dans une liste qui n'est pas une valeur?


Le type de liste de Python a une méthode d'index (x). Il prend un seul paramètre x et renvoie l'index (entier) du premier élément de la liste ayant la valeur x.

Fondamentalement, je dois inverser la méthode d'index (x). J'ai besoin d'obtenir l'index de la première valeur dans une liste qui n'a pas la valeur x. Je serais probablement capable d'utiliser simplement une fonction qui renvoie l'index du premier élément avec une valeur! = Aucun.

Je peux imaginer une implémentation de boucle 'for' avec une variable de compteur incrémentée, mais j'ai l'impression de manquer quelque chose. Existe-t-il une méthode existante ou une construction Python à une ligne capable de gérer cela?

Dans mon programme, la situation se présente lorsque je traite des listes renvoyées par des correspondances complexes de regex. Tous les éléments sauf un de chaque liste ont une valeur Aucun. Si j'avais juste besoin de la chaîne correspondante, je pourrais utiliser une compréhension de liste comme '[x pour x dans [my_list] si x n'est pas aucun]', mais j'ai besoin de l'index pour déterminer quel groupe de capture le match.


16
2018-04-30 23:35


origine


Réponses:


Quitter le premier match est très simple: au lieu de calculer une liste complète (puis de jeter tout sauf le premier élément), utilisez next sur un genexp. En supposant par exemple que vous voulez -1 quand aucun article ne satisfait à la condition d'être != x,

return next((i for i, v in enumerate(L) if v != x), -1)

Ceci est la syntaxe Python 2.6; si vous êtes coincé avec 2,5 ou plus tôt, .next() est une méthode de genexp (ou autre itérateur) et n'accepte pas une valeur par défaut comme le -1 ci-dessus (donc si vous ne voulez pas voir un StopIteration exception, vous devrez utiliser un try/except). Mais alors, il y a est une des raisons pour lesquelles plus de versions ont été faites après 2.5 - amélioration continue de la langue et de ses composants intégrés! -)


17
2018-05-01 03:15



En utilisant une compréhension de liste lorsque vous avez seulement besoin de la première, vous vous sentez visqueux. Utilisez une boucle en boucle et quittez tôt.

>>> lst = [None, None, None, "foo", None]
>>> for i, item in enumerate(lst):
...   if item: break
... else:
...   print "not found"
... 
>>> i
3

5
2018-04-30 23:57



enumerate() renvoie un itérateur qui fournit un tuple de l'index actuel de l'itérable ainsi que de l'élément lui-même.


4
2018-04-30 23:36



[i for i, x in enumerate(my_list) if x != value][0]

Si vous ne savez pas si un élément ne correspond pas, utilisez plutôt ceci:

match = [i for i, x in enumerate(my_list) if x != value]
if match:
    i = match[0]
    # i is your number.

Vous pouvez rendre cela encore plus "fonctionnel" avec les outils itert, mais vous atteindrez bientôt le point où une simple boucle est meilleure. Même les solutions ci-dessus ne sont pas aussi efficaces qu'une boucle for, car elles construisent une liste de tous les indices non correspondants avant de tirer celui qui vous intéresse.


1
2018-04-30 23:38



Une solution idiote basée sur itertools :)

import itertools as it, operator as op, functools as ft

def index_ne(item, sequence):
    sequence= iter(sequence)
    counter= it.count(-1) # start counting at -1
    pairs= it.izip(sequence, counter) # pair them
    get_1st= it.imap(op.itemgetter(0), pairs) # drop the used counter value
    ne_scanner= it.ifilter(ft.partial(op.ne, item), get_1st) # get only not-equals
    try:
        ne_scanner.next() # this should be the first not equal
    except StopIteration:
        return None # or raise some exception, all items equal to item
    else:
        return counter.next() # should be the index of the not-equal item

if __name__ == "__main__":
    import random

    test_data= [0]*20
    print "failure", index_ne(0, test_data)

    index= random.randrange(len(test_data))
    test_data[index]= 1
    print "success:", index_ne(0, test_data), "should be", index

Tout cela pour profiter de la itertools.count compter :)


-1
2018-05-01 00:45