2010-10-31 6 views
1

j'ai un objet très longue chaîne qui a été formaté comme celui-ciconversion chaîne

myString = “[name = john, family = candy, age = 72],[ name = jeff, family = Thomson, age = 24]” 

bien sûr, la chaîne est plus longue que cela. Aussi je ont 3 listes avec des noms associés:

Names = [] 
Families = [] 
Ages  = [] 

Je veux lire ce caractère de chaîne par caractère et prendre les données et l'ajouter dans les listes appropriées. Quelqu'un peut-il m'aider à ce sujet sur la façon de séparer la chaîne en variables? La chose que je besoin est quelque chose comme ceci:

Names = [“john”, “jeff”, ...] 
Families = [“candy”, “Thomson”, ...] 
Ages = [72, 24, ...] 
+0

Il est donc correct d'avoir toute la chaîne en mémoire à la fois? –

+0

oui, il n'y a pas de problème pour cela – user435245

Répondre

5

Cela peut être fait plus facilement en utilisant une regex. Fondamentalement, construire une regex qui extrait le nom, la famille et l'âge de la chaîne et extraire les données pertinentes à partir de tuple retournés pour construire votre list s.

import re 

if __name__=='__main__': 
    myString = "[name = john adams, family = candy, age = 72],[ name = jeff, family = Thomson, age = 24]" 
    answers=re.findall("\\[\\s*name = ([^,]+), family = (\\w+), age = (\\d+)\\]",myString) 
    names=[x[0] for x in answers] 
    families=[x[1] for x in answers] 
    ages=map(int,(x[2] for x in answers)) 

    print "names: ",names 
    print "families: ", families 
    print "ages: ", ages 
+0

+1 - vraiment sympa. – duffymo

+0

Merci pour votre réponse mais si un nom a un espace entre lui par exemple name = "Antoni Red" – user435245

+0

@ user435245: Mis à jour mon regex pour autoriser tous les caractères dans les noms, sauf ','. Je suppose toujours que la famille ne contiendra pas d'espaces, mais vous pouvez aussi changer cela en utilisant la même expression rationnelle pour la famille. – MAK

1

décomposer le problème:

  1. la chaîne dans Parse listes
  2. Chargez les listes dans vos autres listes.

Vous aurez un problème, car les entités entre les virgules ne sont pas de bons dictionnaires.

3
import re 

Names = [] 
Families = [] 
Ages  = [] 
myString = "[name = john, family = candy, age = 72],[ name = jeff, family = Thomson, age = 24" 

myregex = re.compile("name = (?P<name>.*?), family = (?P<family>.*?), age = (?P<age>.*)") 

for list_ in myString.split(']'): 
    found = re.search(myregex, list_).groupdict() 
    Names.append(found['name']) 
    Families.append(found['family']) 
    Ages.append(int(found['age'])) 
+0

+1 pour utiliser des groupes nommés au lieu de se fier au format des données pour ne pas les modifier. Dans un scénario unique, peut-être que cela ne semble pas en valoir la peine, mais il semble que je passe beaucoup de temps à maintenir ce qui était supposé être des scripts uniques. – bgporter

1

Vous devriez analyser cela à une liste de dictionnaires, et non pas trois listes de differente, co-liés uniquement par ordre de données. Comme dans data = [ {"name": "John", "family": "Candy", "age": 72 }, ...]

Une possibilité, si vous ne pouvez pas changer la source de données, est de faire un peu l'analyse syntaxique naïve avec des méthodes de cordes comme Split:

myString = "[name = john, family = candy, age = 72],[ name = jeff, family = Thomson, age = 24]" 

data = [] 
for block in myString.split("]"): 
    if not block: break 
    block = block.split("[")[1] 
    entry_dict = {} 
    for part in block.split(","): 
     key, value = part.split("=") 
     key = key.strip() 
     value = value.strip() 
     if key == "age": value = int(value) 
     entry_dict[key] = value 
    data.append (entry_dict) 

Ou, si vous êtes sur Python 2.7 (ou 3.1) et que vous voulez un code plus court, vous pouvez utiliser un générateur de dict (vous pouvez utiliser des générateurs dans les autres versions, juste créer alist de tuples et en ajoutant un appel « dict »):

myString = « [name = john, famille = bonbons, âge = 72], [nom = jeff, famille = Thomson, âge = 24] "

data = [] 
for block in myString.split("]"): 
    if not block: break 
    block = block.split("[")[1] 
    entry_dict = {} 
    data.append ({(part.split("=")[0].strip(), part.split("=")[1].strip()) for part in block.split(",") }) 

(dans cette version ne convertissaient pas « âge » aux nombres, cependant)