396 votes

Séparation par virgule et suppression des espaces en Python

J'ai un code python qui sépare sur la virgule, mais ne supprime pas l'espace blanc :

>>> string = "blah, lots  ,  of ,  spaces, here "
>>> mylist = string.split(',')
>>> print mylist
['blah', ' lots  ', '  of ', '  spaces', ' here ']

Je préférerais que les espaces blancs soient supprimés comme ceci :

['blah', 'lots', 'of', 'spaces', 'here']

Je suis conscient que je pourrais parcourir la liste en boucle et dépouiller() chaque élément mais, comme il s'agit de Python, je suppose qu'il existe un moyen plus rapide, plus facile et plus élégant de le faire.

700voto

Sean Vieira Points 47080

Utilisez une liste de compréhension -- plus simple, et tout aussi facile à lire qu'une for boucle.

my_string = "blah, lots  ,  of ,  spaces, here "
result = [x.strip() for x in my_string.split(',')]
# result is ["blah", "lots", "of", "spaces", "here"]

Voir : Documentation Python sur la compréhension des listes
Une bonne explication de 2 secondes sur la compréhension des listes.

1 votes

Super bien ! J'ai ajouté un élément comme suit pour me débarrasser des entrées de liste vides. > texte = [x.strip() for x in text.split('.') if x != '']

0 votes

@Sean : le code python invalide/incomplet était-il votre "intention originale du post" ? Selon les branleurs de la revue, c'était le cas : stackoverflow.com/review/suggested-edits/21504253 . Pouvez-vous s'il vous plaît leur dire le contraire en faisant la correction s'ils se trompent (encore) ?

0 votes

L'original était un copié-collé d'un REPL (si je me souviens bien) et le but était de comprendre le concept sous-jacent (utiliser la compréhension de liste pour effectuer une opération) - mais vous avez raison, cela a plus de sens si vous voir cette compréhension de la liste produit une nouvelle liste.

28voto

Sean Points 3056

Je suis venu ajouter :

map(str.strip, string.split(','))

mais a vu que cela avait déjà été mentionné par Jason Orendorff dans un commentaire .

En lisant le commentaire de Glenn Maynard dans la même réponse, qui suggérait de préférer les listes de compréhension aux cartes, je me suis demandé pourquoi. J'ai supposé qu'il voulait dire pour des raisons de performance, mais bien sûr il aurait pu vouloir dire pour des raisons stylistiques, ou autre chose (Glenn ?).

Un test rapide (peut-être erroné ?) sur ma boîte en appliquant les trois méthodes dans une boucle a donc révélé.. :

[word.strip() for word in string.split(',')]
$ time ./list_comprehension.py 
real    0m22.876s

map(lambda s: s.strip(), string.split(','))
$ time ./map_with_lambda.py 
real    0m25.736s

map(str.strip, string.split(','))
$ time ./map_with_str.strip.py 
real    0m19.428s

réalisation de map(str.strip, string.split(',')) le gagnant, bien qu'il semble qu'ils soient tous dans la même fourchette.

Il est certain qu'une carte (avec ou sans lambda) ne doit pas nécessairement être exclue pour des raisons de performances, et pour moi, elle est au moins aussi claire qu'une compréhension de liste.

Editar:

Python 2.6.5 sur Ubuntu 10.04

26voto

tbc0 Points 129

Diviser en utilisant une expression régulière. Notez que j'ai rendu le cas plus général avec des espaces en tête. La compréhension de la liste consiste à supprimer les chaînes nulles au début et à la fin.

>>> import re
>>> string = "  blah, lots  ,  of ,  spaces, here "
>>> pattern = re.compile("^\s+|\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['blah', 'lots', 'of', 'spaces', 'here']

Cela fonctionne même si ^\s+ ne correspond pas :

>>> string = "foo,   bar  "
>>> print([x for x in pattern.split(string) if x])
['foo', 'bar']
>>>

Voici pourquoi vous avez besoin de ^ \s + :

>>> pattern = re.compile("\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['  blah', 'lots', 'of', 'spaces', 'here']

Vous voyez les espaces de tête dans blah ?

Clarification : le texte ci-dessus utilise l'interpréteur Python 3, mais les résultats sont les mêmes en Python 2.

9 votes

Je crois [x.strip() for x in my_string.split(',')] est plus pythique pour la question posée. Peut-être y a-t-il des cas où ma solution est nécessaire. Je mettrai à jour ce contenu si j'en rencontre un.

0 votes

Pourquoi est-ce que ^\s+ nécessaire ? J'ai testé votre code sans cela et cela ne fonctionne pas, mais je ne sais pas pourquoi.

0 votes

Si j'utilise re.compile("^\s*,\s*$") Le résultat est [' blah, lots , of , spaces, here '] .

18voto

user489041 Points 6362

Il suffit de supprimer les espaces blancs de la chaîne avant de la diviser.

mylist = my_string.replace(' ','').split(',')

17 votes

Il y a un problème si les éléments séparés par des virgules contiennent des espaces incorporés, par exemple "you just, broke this" .

2 votes

Bon sang, un -1 pour ça. Vous êtes durs, les gars. Cela a résolu son problème, à condition que son échantillon de données ne soit constitué que de mots uniques et qu'il n'y ait aucune spécification que les données soient des phrases. Mais bon, je suppose que c'est comme ça que vous fonctionnez par ici.

0 votes

Merci quand même, utilisateur. Pour être juste, j'ai spécifiquement demandé split et ensuite strip() et strip enlève les espaces blancs de début et de fin et ne touche rien entre les deux. Une légère modification et votre réponse fonctionnerait parfaitement, cependant : mylist = mystring.strip().split(',') bien que je ne sache pas si cela est particulièrement efficace.

12voto

Brad Montgomery Points 945

Je sais que la réponse à cette question a déjà été donnée, mais si vous êtes amené à faire cela souvent, les expressions régulières peuvent être une meilleure solution :

>>> import re
>>> re.sub(r'\s', '', string).split(',')
['blah', 'lots', 'of', 'spaces', 'here']

El \s correspond à n'importe quel caractère d'espacement, et nous le remplaçons simplement par une chaîne vide. '' . Vous pouvez trouver plus d'informations ici : http://docs.python.org/library/re.html#re.sub

3 votes

Votre exemple ne fonctionnerait pas sur les chaînes de caractères contenant des espaces. "pour, exemple ceci, un" deviendrait "pour", "exemple ceci", "un". Je ne dis pas que c'est une MAUVAISE solution (elle fonctionne parfaitement dans mon exemple), mais tout dépend de la tâche à accomplir !

0 votes

Oui, c'est très correct ! Vous pourriez probablement ajuster la regexp pour qu'elle puisse gérer les chaînes avec des espaces, mais si la compréhension de la liste fonctionne, je dirais qu'il faut s'y tenir ;)

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