J'ai une chaîne CSV où certains des éléments peuvent être entourés de {} avec des virgules à l'intérieur. Je voulais collecter les valeurs de chaîne dans une liste.

Quelle est la façon la plus pythonique de collecter les valeurs dans une liste?

Exemple 1: 'a,b,c', sortie attendue ['a', 'b', 'c']

Exemple 2: '{aa,ab}, b, c', sortie attendue ['{aa,ab}','b','c']

Exemple 3: '{aa,ab}, {bb,b}, c', sortie attendue ['{aa,ab}', '{bb,b}', 'c']

J'ai essayé de travailler avec s.split(','), cela fonctionne pour l'exemple 1 mais va gâcher pour les cas 2 et 3.

Je pense que cette question (Comment diviser mais ignorer les séparateurs dans les chaînes entre guillemets, en python?) est très similaire à mon problème. Mais je ne peux pas comprendre la syntaxe regex appropriée à utiliser.

2
rph 11 avril 2018 à 11:25

3 réponses

Meilleure réponse

La solution est très similaire en fait:

import re
PATTERN = re.compile(r'''\s*((?:[^,{]|\{[^{]*\})+)\s*''')
data = '{aa,ab}, {bb,b}, c'
print(PATTERN.split(data)[1::2])

Va donner:

['{aa,ab}', '{bb,b}', 'c']
6
Marco Pantaleoni 11 avril 2018 à 08:35

Notez qu'il n'est pas nécessaire d'utiliser une expression régulière, vous pouvez simplement utiliser du Python pur:

s = '{aa,ab}, {bb,b}, c'
commas = [i for i, c in enumerate(s) if c == ',' and \
                                             s[:i].count('{') == s[:i].count('}')]
[s[2:b] for a, b in zip([-2] + commas, commas + [None])]
#['{aa,ab}', '{bb,b}', 'c']
1
Joe Iddon 11 avril 2018 à 09:46

Une façon plus lisible (du moins pour moi) consiste à expliquer ce que vous recherchez: quelque chose entre crochets {} ou quelque chose qui ne contient que des caractères alphanumériques:

import re 

examples = [
  'a,b,c',
  '{aa,ab}, b, c',
  '{aa,ab}, {bb,b}, c'
]

for example in examples:
  print(re.findall(r'(\{.+?\}|\w+)', example))

Il imprime

['a', 'b', 'c']
['{aa,ab}', 'b', 'c']
['{aa,ab}', '{bb,b}', 'c']
3
Guybrush 11 avril 2018 à 08:39