Python >> Tutoriel Python >  >> Python Tag >> RegEx

Manière pythonique de trouver la dernière position dans une chaîne correspondant à une expression régulière négative

Vous pouvez utiliser re.finditer pour extraire les positions de départ de tous les matchs et renvoyer le dernier de la liste. Essayez ce code Python :

import re
print([m.start(0) for m in re.finditer(r'\D', 'uiae1iuae200')][-1])

Impressions :

8

Modifier : Pour rendre la solution un peu plus élégante pour qu'elle se comporte correctement pour tous les types d'entrées, voici le code mis à jour. Maintenant, la solution va sur deux lignes car la vérification doit être effectuée si la liste est vide, elle imprimera -1 sinon la valeur de l'index :

import re

arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']

for s in arr:
    lst = [m.start() for m in re.finditer(r'\D', s)]
    print(s, '-->', lst[-1] if len(lst) > 0 else None)

Imprime ce qui suit, où si aucun index de ce type n'est trouvé, imprime alors None au lieu d'index :

 --> None
123 --> None
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19

Modification 2 : Comme OP l'a indiqué dans son message, \d n'était qu'un exemple avec lequel nous avons commencé, grâce auquel j'ai trouvé une solution pour travailler avec n'importe quelle expression régulière générale. Mais, si ce problème doit vraiment être résolu avec \d seulement, alors je peux donner une meilleure solution qui ne nécessiterait pas du tout la compréhension de la liste et qui peut être facilement écrite en utilisant une meilleure expression régulière pour trouver la dernière occurrence de caractère non numérique et imprimer sa position. Nous pouvons utiliser .*(\D) regex pour trouver la dernière occurrence de non-chiffre et imprimer facilement son index en utilisant le code Python suivant :

import re

arr = ['', '123', 'uiae1iuae200', 'uiae1iuae200aaaaaaaa']

for s in arr:
    m = re.match(r'.*(\D)', s)
    print(s, '-->', m.start(1) if m else None)

Imprime la chaîne et leur index correspondant de caractères non numériques et None si pas trouvé :

 --> None
123 --> None
uiae1iuae200 --> 8
uiae1iuae200aaaaaaaa --> 19

Et comme vous pouvez le voir, ce code n'a pas besoin d'utiliser de compréhension de liste et est meilleur car il peut simplement trouver l'index par un seul appel regex à match .

Mais dans le cas où OP signifiait effectivement qu'il devait être écrit en utilisant n'importe quel modèle regex général, alors mon code ci-dessus utilisant la compréhension sera nécessaire. Je peux même l'écrire comme une fonction qui peut prendre la regex (comme \d ou même complexe) comme argument et générera dynamiquement un négatif de regex passé et l'utilisera dans le code. Faites-moi savoir si cela est vraiment nécessaire.


Pour moi, il semble que vous souhaitiez simplement la dernière position qui correspond à un modèle donné (dans ce cas, il ne s'agit pas d'un modèle numérique).
C'est aussi pythonique que possible :

import re

string = 'uiae1iuae200'
pattern = r'[^0-9]'

match = re.match(fr'.*({pattern})', string)
print(match.end(1) - 1 if match else None)

Sortie :

8

Ou exactement la même chose qu'une fonction et avec plus de cas de test :

import re


def last_match(pattern, string):
    match = re.match(fr'.*({pattern})', string)
    return match.end(1) - 1 if match else None


cases = [(r'[^0-9]', 'uiae1iuae200'), (r'[^0-9]', '123a'), (r'[^0-9]', '123'), (r'[^abc]', 'abcabc1abc'), (r'[^1]', '11eea11')]

for pattern, string in cases:
    print(f'{pattern}, {string}: {last_match(pattern, string)}')

Sortie :

[^0-9], uiae1iuae200: 8
[^0-9], 123a: 3
[^0-9], 123: None
[^abc], abcabc1abc: 6
[^1], 11eea11: 4