2008-10-09 15 views
64

J'ai une chaîne qui ressemble à ceci:Fractionnement une chaîne séparée des points-virgules à un dictionnaire, en Python

"Name1=Value1;Name2=Value2;Name3=Value3" 

est-il intégré dans la classe/fonction en Python qui prendra cette chaîne et construire un dictionnaire, comme si je l'avais fait ceci:

dict = { 
    "Name1": "Value1", 
    "Name2": "Value2", 
    "Name3": "Value3" 
} 

J'ai regardé à travers les modules disponibles mais ne peut pas sembler trouver quelque chose qui correspond.


Merci, je ne sais comment faire moi-même le code approprié, mais étant donné que ces solutions sont généralement assez petites champs de mines qui attendent de se produire (par exemple quelqu'un écrit:. Name1 = « Valeur1 = 2 »;), etc. alors je préfère habituellement une fonction pré-testée.

Je le ferai moi-même alors.

+0

Est-ce que votre question nécessite de prendre en charge 's = r'Name1 = 'Value = 2'; Name2 = Value2; Name3 = Value3; Name4 =" Va \ "lue; \ n3" ''input (note: un point-virgule à l'intérieur d'une citation chaîne, une citation est échappée en utilisant une barre oblique inverse, l'échappement '\ n' est utilisé, les guillemets simples et doubles sont utilisés)? – jfs

+0

Cette question est à moi depuis plus de 6 ans, le code qui impliquait cela a été remplacé depuis longtemps :) Et non, il ne nécessitait pas de support pour les citations, je voulais juste avoir un f onction au lieu d'écrire quelque chose moi-même. Cependant, le code a disparu depuis longtemps. –

Répondre

100

Il n'y a pas builtin, mais vous pouvez y arriver assez simplement avec une compréhension du générateur:

s= "Name1=Value1;Name2=Value2;Name3=Value3" 
dict(item.split("=") for item in s.split(";")) 

[Modifier] À partir de votre mise à jour, vous indiquez que vous devrez peut-être gérer en citant. Cela complique les choses, en fonction de ce que le format exact que vous recherchez est (quelles citations sont acceptées, quels chars d'échappement, etc.). Vous pouvez regarder le module csv pour voir s'il peut couvrir votre format. Voici un exemple: (Notez que l'API est un peu maladroite pour cet exemple, car CSV est conçu pour parcourir une séquence d'enregistrements, d'où les appels .next() que je fais pour regarder la première ligne. selon vos besoins):

>>> s = "Name1='Value=2';Name2=Value2;Name3=Value3" 

>>> dict(csv.reader([item], delimiter='=', quotechar="'").next() 
     for item in csv.reader([s], delimiter=';', quotechar="'").next()) 

{'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1=2'} 

en fonction de la structure exacte de votre format, vous devrez peut-être écrire votre propre analyseur simple, cependant.

+0

le code ne gère pas la citation, essayez: 's =" Nom1 = 'Valeur; 2'; Nom2 = Valeur2; Nom3 = Valeur3 "' (remarque: point-virgule dans la valeur 'Nom1' cité). – jfs

4

Cela se rapproche de faire ce que vous vouliez:

>>> import urlparse 
>>> urlparse.parse_qs("Name1=Value1;Name2=Value2;Name3=Value3") 
{'Name2': ['Value2'], 'Name3': ['Value3'], 'Name1': ['Value1']} 
+1

il casse s'il y a '&' ou '%' dans l'entrée. – jfs

-2
easytiger $ cat test.out test.py | sed 's/^/ /' 
p_easytiger_quoting:1.84563302994 
{'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1'} 
p_brian:2.30507516861 
{'Name2': 'Value2', 'Name3': "'Value3'", 'Name1': 'Value1'} 
p_kyle:7.22536420822 
{'Name2': ['Value2'], 'Name3': ["'Value3'"], 'Name1': ['Value1']} 
import timeit 
import urlparse 

s = "Name1=Value1;Name2=Value2;Name3='Value3'" 

def p_easytiger_quoting(s): 
    d = {} 
    s = s.replace("'", "") 
    for x in s.split(';'): 
     k, v = x.split('=') 
     d[k] = v 
    return d 


def p_brian(s): 
    return dict(item.split("=") for item in s.split(";")) 

def p_kyle(s): 
    return urlparse.parse_qs(s) 



print "p_easytiger_quoting:" + str(timeit.timeit(lambda: p_easytiger_quoting(s))) 
print p_easytiger_quoting(s) 


print "p_brian:" + str(timeit.timeit(lambda: p_brian(s))) 
print p_brian(s) 

print "p_kyle:" + str(timeit.timeit(lambda: p_kyle(s))) 
print p_kyle(s) 
+0

Cela ne répond pas à la question, car il ne gère pas les citations. Essayez 's =" Name1 = 'Value1 = 2'; Name2 = Value2 "et' csv' (comme dans la réponse acceptée de Brian) ou 'parse_qs' (comme dans Kyle) l'obtiendra, tandis que le vôtre lèvera un' ValueError' . Le PO dit spécifiquement que «des solutions aussi minuscules sont généralement des champs de mines en attente de réalisation», ce qui explique pourquoi il veut une solution intégrée ou une autre solution bien testée, et il donne un exemple qui enfreindra votre code. – abarnert

+0

Ahh je n'ai pas vu ça. encore. il serait encore plus rapide que toutes vos solutions de préparer ceux de la chaîne principale avant l'itération et de rappeler la fonction de remplacement des milliers de fois. Je vais mettre à jour – easytiger

+0

Je ne sais pas comment vous allez le préparer. Mais même si vous le faites, cela semble exactement ce dont le PO avait peur dans une solution simple. Es-tu sûr qu'il n'y a pas d'autres mines devant? Pouvez-vous le prouver à la satisfaction du PO? – abarnert

-1

Si votre Valeur1, Valeur2 ne sont que des espaces réservés pour les valeurs réelles, vous pouvez également utiliser la fonction dict() en combinaison avec eval().

>>> s= "Name1=1;Name2=2;Name3='string'" 
>>> print eval('dict('+s.replace(';',',')+')') 
{'Name2: 2, 'Name3': 'string', 'Name1': 1} 

C'est beacuse la fonction dict() comprendre la syntaxe dict(Name1=1, Name2=2,Name3='string'). Les espaces dans la chaîne (par exemple après chaque point-virgule) sont ignorés. Mais notez que les valeurs de chaîne nécessitent des guillemets.

+0

Merci, upvote string.replace a bien fonctionné. Je ne sais pas pourquoi je ne pouvais pas diviser. J'ai fait i = textcontrol.GetValue() sur la boîte tc, puis o = i.split (';') mais ne produisait pas une chaîne qui se plaignait du format, contrairement à replace. – Iancovici

+1

's.replace (la solution basée sur ';'' est interrompue s'il y a ';' dans une valeur entre guillemets. [Eval is evil] (http://stackoverflow.com/a/9558001/4279) ce cas. – jfs

0

Il peut être fait simplement par join et la compréhension liste

», 'join ([' % s =% s'% x pour x dans d.items()])

>>d = {'a':1, 'b':2} 
>>','.join(['%s=%s'%x for x in d.items()]) 
>>'a=1,b=2'