766 votes

Séparation d'une chaîne avec plusieurs délimiteurs en Python

J'ai trouvé quelques réponses en ligne, mais je n'ai aucune expérience des expressions régulières, ce qui est, je crois, ce dont on a besoin ici.

J'ai une chaîne de caractères qui doit être séparée par un " ;" ou un ",". C'est-à-dire qu'il doit s'agir soit d'un point-virgule, soit d'une virgule suivie d'un espace. Les virgules individuelles sans espace de queue doivent être laissées intactes.

Exemple de chaîne :

"b-staged divinylsiloxane-bis-benzocyclobutene [124221-30-3], mesitylene [000108-67-8]; polymerized 1,2-dihydro-2,2,4- trimethyl quinoline [026780-96-1]"

doit être divisé en une liste contenant les éléments suivants :

('b-staged divinylsiloxane-bis-benzocyclobutene [124221-30-3]' , 'mesitylene [000108-67-8]', 'polymerized 1,2-dihydro-2,2,4- trimethyl quinoline [026780-96-1]')

1242voto

Jonathan Points 11842

Heureusement, Python intègre cette fonctionnalité :)

import re
re.split('; |, ',str)

Mise à jour :
Suite à votre commentaire :

>>> a='Beautiful, is; better*than\nugly'
>>> import re
>>> re.split('; |, |\*|\n',a)
['Beautiful', 'is', 'better', 'than', 'ugly']

0 votes

@Paul Il n'y en a pas. Vous ne comprenez pas bien les regex si vous pensez que c'est le cas. Voir mon commentaire sur votre message ci-dessous.

28 votes

Je préférerais l'écrire comme suit : re.split(r';|, \s ', a) en remplaçant ' ' (caractère d'espacement) par ' \s ' (espace blanc), sauf si le caractère espace est une exigence stricte.

114 votes

Je me demande pourquoi (regular) split ne peut pas accepter une liste, cela semble être un moyen plus évident au lieu d'encoder plusieurs options dans une ligne.

484voto

Joe Points 3175

Faites un str.replace('; ', ', ') et ensuite un str.split(', ')

32 votes

+1 ; très spécifique et précis, pas générique. Ce qui est souvent mieux.

97 votes

Supposons que vous ayez 5 délimitations, vous devez parcourir votre chaîne 5x fois.

11 votes

C'est très mauvais pour les performances

184voto

Kos Points 29125

Voici une méthode sûre pour tout itérable de délimiteurs, en utilisant des expressions régulières :

>>> import re
>>> delimiters = "a", "...", "(c)"
>>> example = "stackoverflow (c) is awesome... isn't it?"
>>> regexPattern = '|'.join(map(re.escape, delimiters))
>>> regexPattern
'a|\\.\\.\\.|\\(c\\)'
>>> re.split(regexPattern, example)
['st', 'ckoverflow ', ' is ', 'wesome', " isn't it?"]

re.escape permet de construire le motif automatiquement et d'avoir les délimiteurs échappés de façon agréable.

Voici cette solution sous forme de fonction pour votre plaisir de copier-coller :

def split(delimiters, string, maxsplit=0):
    import re
    regexPattern = '|'.join(map(re.escape, delimiters))
    return re.split(regexPattern, string, maxsplit)

Si vous avez l'intention d'effectuer des séparations fréquentes en utilisant les mêmes délimiteurs, compilez votre expression régulière au préalable comme décrit et utilisez RegexObject.split .


Si vous souhaitez laisser les délimiteurs d'origine dans la chaîne de caractères, vous pouvez modifier la regex pour qu'elle utilise un filtre de type assertion de regard derrière soi à la place :

>>> import re
>>> delimiters = "a", "...", "(c)"
>>> example = "stackoverflow (c) is awesome... isn't it?"
>>> regexPattern = '|'.join('(?<={})'.format(re.escape(delim)) for delim in delimiters)
>>> regexPattern
'(?<=a)|(?<=\\.\\.\\.)|(?<=\\(c\\))'
>>> re.split(regexPattern, example)
['sta', 'ckoverflow (c)', ' is a', 'wesome...', " isn't it?"]

(remplacer ?<= con ?= pour attacher les délimiteurs au côté droit, au lieu de gauche)

4 votes

+1 c'est la solution la plus sûre et la plus extensible.

1 votes

Sachez que l'utilisation de def split() surchargera la fonction python split()

5 votes

@Mausy5043 Il n'y a pas de module intégré. split en Python, vous le confondez peut-être avec str.split méthode ?

94voto

Paul Points 472

En réponse à la réponse de Jonathan ci-dessus, cela ne semble fonctionner que pour certains délimiteurs. Par exemple :

>>> a='Beautiful, is; better*than\nugly'
>>> import re
>>> re.split('; |, |\*|\n',a)
['Beautiful', 'is', 'better', 'than', 'ugly']

>>> b='1999-05-03 10:37:00'
>>> re.split('- :', b)
['1999-05-03 10:37:00']

En mettant les délimiteurs entre crochets, cela semble fonctionner plus efficacement.

>>> re.split('[- :]', b)
['1999', '05', '03', '10', '37', '00']

19 votes

Elle fonctionne pour tous les délimiteurs que vous spécifiez. Une regex de - : correspond exactement - : et ne divisera donc pas la chaîne date/heure. Une regex de [- :] correspond à - , <space> ou : et divise ainsi la chaîne date/heure. Si vous voulez diviser uniquement sur - y : alors votre regex devrait être soit [-:] o -|: et si vous voulez partager sur - , <space> y : alors votre regex devrait être soit [- :] o -| |: .

6 votes

@alldayremix Je vois mon erreur : j'ai manqué le fait que votre regex contient le OU |. Je l'ai aveuglément identifié comme un séparateur souhaité.

0 votes

Merci, j'avais besoin des parenthèses pour mon cas d'utilisation.

39voto

Jochen Ritzel Points 42916

Voici à quoi ressemblent les regex :

import re
# "semicolon or (a comma followed by a space)"
pattern = re.compile(r";|, ")

# "(semicolon or a comma) followed by a space"
pattern = re.compile(r"[;,] ")

print pattern.split(text)

0 votes

Merci, j'avais la bonne idée, je ne savais juste pas comment séparer les délimiteurs, maintenant je vois que vous utilisez le symbole |.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X