J'ai une chaîne qui ressemble à ceci:
"Name1=Value1;Name2=Value2;Name3=Value3"
Existe-t-il une classe / fonction intégrée en Python qui prendra cette chaîne et construira un dictionnaire, comme si j'avais fait ceci:
dict = {
"Name1": "Value1",
"Name2": "Value2",
"Name3": "Value3"
}
J'ai parcouru les modules disponibles mais je n'arrive pas à trouver quoi que ce soit qui corresponde.
Merci, je sais comment créer moi-même le code pertinent, mais comme ces petites solutions sont généralement des champs de mines qui attendent d'arriver (c'est-à-dire que quelqu'un écrit: Name1 = 'Value1 = 2';) etc. alors je préfère généralement des pré- fonction testée.
Je vais le faire moi-même alors.
python
string
dictionary
split
Lasse V. Karlsen
la source
la source
s = r'Name1='Value=2';Name2=Value2;Name3=Value3;Name4="Va\"lue;\n3"'
entrée (note: un point-virgule dans une chaîne entre guillemets, un guillemet est échappé à l'aide d'une barre oblique inverse, un\n
échappement est utilisé, des guillemets simples et doubles sont utilisés)?Réponses:
Il n'y a pas de builtin, mais vous pouvez accomplir cela 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 les devis. Cela complique les choses, selon le format exact que vous recherchez (quels caractères de citation sont acceptés, quels caractères d'échappement, etc.). Vous voudrez peut-être 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 simplement la première ligne. répondre à 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.
la source
s = "Name1='Value;2';Name2=Value2;Name3=Value3"
(note: point-virgule dans laName1
valeur citée ).AttributeError: '_csv.reader' object has no attribute 'next'
me jette . Bien sûr que je l'ai faitimport csv
.Cela revient à faire ce que vous vouliez:
>>> import urlparse >>> urlparse.parse_qs("Name1=Value1;Name2=Value2;Name3=Value3") {'Name2': ['Value2'], 'Name3': ['Value3'], 'Name1': ['Value1']}
la source
&
ou%
dans l'entrée.&
ou%
- à tout le moins, il convient de mentionner que la réponse ne fonctionne pas pour de telles chaînes.s1 = "Name1=Value1;Name2=Value2;Name3=Value3" dict(map(lambda x: x.split('='), s1.split(';')))
la source
Cela peut être simplement fait par jointure de chaîne et compréhension de liste
",".join(["%s=%s" % x for x in d.items()])
>>d = {'a':1, 'b':2} >>','.join(['%s=%s'%x for x in d.items()]) >>'a=1,b=2'
la source
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)
la source
s = "Name1='Value1=2';Name2=Value2" and
csv` (comme dans la réponse acceptée de Brian) ouparse_qs
(comme dans Kyle) le fera correctement, tandis que le vôtre augmentera unValueError
. L'OP dit spécifiquement que "ces petites solutions sont généralement des champs de mines qui attendent de se produire", c'est pourquoi il veut une solution intégrée ou une autre solution bien testée, et il donne un exemple qui cassera votre code.s.replace
ne fait rien du tout; il renvoie simplement une nouvelle chaîne que vous ignorez. Deuxièmement, même si vous avez bien compris (s = s.replace…
), cela ne résout pas le problème, cela en ajoute simplement un nouveau par-dessus. Essayez-le sur mon exemple ou sur les OP.Name='Value1=2';
. Et votre code ne le gère pas. Et je ne sais pas comment vous désinfecteriez cela sans l'analyser d'une manière qui sera tout aussi lenteurlparse
oucsv
en premier lieu.SI vos Value1, Value2 ne sont que des espaces réservés pour les valeurs réelles, vous pouvez également utiliser la
dict()
fonction en combinaison aveceval()
.>>> s= "Name1=1;Name2=2;Name3='string'" >>> print eval('dict('+s.replace(';',',')+')') {'Name2: 2, 'Name3': 'string', 'Name1': 1}
C'est parce que la
dict()
fonction comprend la syntaxedict(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.la source
s.replace(';'
-solution basée sur les ruptures s'il y a à l';
intérieur d'une valeur citée. eval est mal et il est inutile dans ce cas.