Python: cherche une chaîne de caractère
RésoluBonjour,
Je lis des codes data matrix dont les composants sont spécifiés par des préfixes sous la forme '(XX)'
Exemple: (10)215(17)270109 ou (10)215(96)A(L(11)04122024
Je récupère cette chaîne de caractère en input, et je souhaite en extraire les différentes composantes. Je sais trouver le préfixe (10) et sa position dans la chaîne, mais je ne sais pas trouver la position du préfixe suivant.
Je pourrais chercher uniquement le caractère '(', mais je crains qu'il n'apparaisse dans la donnée (par exemple: A)L)
Je voudrais donc chercher la prochaine occurrence de '(**)', les 2 étoiles pouvant être n'importe quel chiffre...
Comment faire en python?
- Rechercher un mot dans une chaîne de caractère python
- Caractère ascii - Guide
- Trousseau mot de passe iphone - Guide
- Caractère spéciaux - Guide
- Mot de passe - Guide
- Caractères spéciaux : comment les saisir facilement - Guide
9 réponses
Je ne maitrise pas Python, mais je verrais bien un truc comme ça :
import re print(re.split(r'(\d+)', s_nums))
Adapté de :
https://note.nkmk.me/en/python-split-rsplit-splitlines-re/#split-a-string-by-regex-resplit
\d veut dire 'digit', donc chiffre et {2} veut dire 2 occurrences de \d, entourées par les parenthèses.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionSi la chaîne est bien une alternance de nombres entre parenthèses suivi d'un autre nombre:
ligne = "(10)215(17)270109"
liste = ligne.replace("(", ",(").replace(")", "),").split(",")
liste.pop(0) # enlever la chaîne vide au début
Les éléments parenthèsés seraient en indices pairs (0, 2, ...) dans une liste.
On enlève les parenthèses comme suit:
element = element.replace("(", "").replace(")", "")
Il faudra ensuite convertir tous les éléments en nombre si requis.
Meilleurs vœux à tous et toutes.
@pierrotlefou StatutMembre ton exemple me retourne cette liste :
[' (10)', '215(17)', '270109']
l'exemple de @Phil_1857 StatutMembre est mieux adapté, en simplifiant un peu le pattern :
re.findall(r"\((\d{2})\)", s)
'lut,
Sans expressions régulières.
def find_digits_between_brackets(string): i = 0 values = {} while True: i = string.find('(', i) if i == -1: break if string[i+1:i+3].isdigit() and string[i+3] == ')': values[i+1] = int(string[i+1:i+3]) i += 1 return values s = '(10)215(96)A(L(11)04122024' #position => nombre print(find_digits_between_brackets(s))
Peu d'intérêt, mais uniquement pour montrer une autre façon de faire ^-^
Certains préfèreront ta méthode, car beaucoup plus lisible qu'une expression régulière.
Pour le fun en reprenant ton idée du dictionnaire pour y stocker l'indice :
import re def find_digits_between_brackets(string): pattern = re.compile(r"\((\d{2})\)") return {match.start(1): int(match.group(1)) for match in pattern.finditer(string)} s = "(10)215(96)A(L(11)04122024" # position => nombre print(find_digits_between_brackets(s))
Bonjour,
Réponse courte
En croisant les idées de @blux StatutModérateur (#3) et PierrotLeFou (#6), on peut écrire plus simplement :
import re s = "(10)215(96)A(L(11)04122024" print(s) r = re.compile(r"\(\d+\)") pairs = [ (m.start(), m.end()) for m in re.finditer(r, s) ] start = 0 for (i, j) in pairs: outside = s[start:i] inside = s[i:j] if outside: print(f"outside = {outside}") print(f"inside = {inside}") start = j outside = s[j:] print(f"outside = {outside}")
Résultat :
(10)215(96)A(L(11)04122024 inside = (10) outside = 215 inside = (96) outside = A(L inside = (11)
Réponse détaillée
Étant donné la boucle que ça donne, ça peut valoir le coup de faire une fonction avec les callbacks adéquates. Le code devient :
import re RE_DATA_MATRIX = re.compile(r"\(\d+\)") class ParseDataMatrixVisitor: def on_inside(s, i, j): pass def on_outside(s, i, j): pass class DefaultParseDataMatrixVisitor(ParseDataMatrixVisitor): def inside(self, s: str, i: int, j: int): print("Inside", s[i:j]) def outside(self, s: str, i: int, j: int): print("Outside", s[i:j]) def parse_data(s, vis: ParseDataMatrixVisitor = None): if vis is None: vis = DefaultParseDataMatrixVisitor() pairs = [ (m.start(), m.end()) for m in re.finditer(RE_DATA_MATRIX, s) ] start = 0 for (i, j) in pairs: if start < i: vis.outside(s, start, i) vis.inside(s, i, j) start = j vis.outside(s, j, None) if __name__ == "__main__": s = "(10)215(96)A(L(11)04122024" print(s) vis = DefaultParseDataMatrixVisitor() parse_data(s, vis)
Réponse finale
À présent, tout est prêt pour faire ce qu'on veut de ces données. Si par exemple, on veut reconstituer un dictionnaire on écrit juste le visiteur adéquat, voici ce qu'on peut écrire :
import re RE_DATA_MATRIX = re.compile(r"\(\d+\)") class ParseDataMatrixVisitor: def on_inside(s, i, j): pass def on_outside(s, i, j): pass class DictParseDataMatrixVisitor(ParseDataMatrixVisitor): def __init__(self): self.last_key = None self.dict = dict() def inside(self, s: str, i: int, j: int): self.last_key = s[i:j].lstrip("(").rstrip(")") def outside(self, s: str, i: int, j: int): last_value = s[i:j] self.dict[self.last_key] = last_value def parse_data(s, vis: ParseDataMatrixVisitor = None): if vis is None: vis = DefaultParseDataMatrixVisitor() pairs = [ (m.start(), m.end()) for m in re.finditer(RE_DATA_MATRIX, s) ] start = 0 for (i, j) in pairs: if start < i: vis.outside(s, start, i) vis.inside(s, i, j) start = j vis.outside(s, j, None) if __name__ == "__main__": s = "(10)215(96)A(L(11)04122024" print(s) vis = DictParseDataMatrixVisitor() parse_data(s, vis) print(vis.dict)
Résultat :
(10)215(96)A(L(11)04122024 {'10': '215', '96': 'A(L', '11': '04122024'}
Bonne chance
Oui mais en l'absence de plus de précision, on ne sait pas s'il ne veut récupérer que les données entre parenthèses ou tout le reste pour en faire par exemple, un tableau associatif/dictionnaire.