manip de string pour en extraire des listes

A10A14A28B33B44C17C21D6D18D25E13E15E20E35F0F1F0F19F5 devient A=[10,14,28] et B=[33,44] etc.

a marqué ce sujet comme résolu.

Salut, je ne sais pas si il existe une methode de string ou de regex pour m’eviter un arrachage de cheveux pour obtenir le resultat suivant: partant de la string

myString = "A10A14A28B33B44C17C21D6D18D25E13E15E20E35F0F1F0F19F5"

je voudrais obtenir

A=[10,14,28]
B=[33,44]
C=[17,21] 

etc. Dans la string, l’odre sera toujours donné dans l’ordre de l' alphabet, et les entiers du petit au plus grand, à l' interieur d’une lettre donnée (sauf sur le segment F). la taille globale de la chaine myString reste fixe.

+0 -0

Salut,

J’imagine que tu parles de Python ?

Déjà je dirais que la première approche est de découper ta chaîne en jetons, tu peux faire ça assez facilement avec une expression rationnelle (regex) : chaque jeton est composée d’une lettre et d’un nombre (une suite de chiffres), soit [A-Z][0-9]+.

Ainsi,

>>> import re
>>> re.findall(r'[A-Z][0-9]+', myString)
['A10', 'A14', 'A28', 'B33', 'B44', 'C17', 'C21', 'D6', 'D18', 'D25', 'E13', 'E15', 'E20', 'E35', 'F0', 'F1', 'F0', 'F19', 'F5']

La suite consiste à récupérer les nombres associés à chaque lettre, avec les conversions que ça implique, et à les stocker dans la liste correspondante. Le plus simple pour ça est d’utiliser un dictionnaire lettre ⇒ liste de nombres.

De plus les dictionnaires ont une méthode setdefault bien pratique pour ça : ça permet de s’assurer qu’une clé sera présente dans le dictionnaire (donc d’avoir une liste déjà présente, prête à être remplie) :

>>> tokens = re.findall(r'[A-Z][0-9]+', myString)
>>> groups = {}
>>> for token in tokens:
...     letter = token[0]
...     number = int(token[1:])
...     groups.setdefault(letter, []).append(number)
... 
>>> groups
{'A': [10, 14, 28], 'B': [33, 44], 'C': [17, 21], 'D': [6, 18, 25], 'E': [13, 15, 20, 35], 'F': [0, 1, 0, 19, 5]}

Si tu es familier avec groupby du module itertools et si tes éléments dans myString sont toujours bien ordonnés, ça peut aussi se faire en une ligne :

>>> from itertools import groupby
>>> {letter: [int(t[1:]) for t in group] for letter, group in groupby(tokens, key=lambda t: t[0])}
{'A': [10, 14, 28], 'B': [33, 44], 'C': [17, 21], 'D': [6, 18, 25], 'E': [13, 15, 20, 35], 'F': [0, 1, 0, 19, 5]}

Pour chipoter sur la réponse d’entwanne (qui est excellente), les expressions régulières possèdent un mécanisme de groupement avec l’operateur (...) permettant d’éviter le redécoupage de la sous-chaîne trouvé. Bon dans ce cas là ça ne change vraiment pas grand chose1 mais c’est dommage de refaire à la main ce que l’expression régulière a déjà fait de toute manière.

import re

groups = {}
for token in re.findall(r"([A-Z])(\d+)", myString):
    letter = token[0]
    number = int(token[1])
    groups.setdefault(letter, []).append(number)

  1. On économise littéralement juste le caractère :, bien qu’en étant honnête c’est l’expressivité de Python qui masque ce qui n’est conceptuellement pas si trivial que ça
+4 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte