15

Kilka razy spotkałem się z tym problemem i nie mogę wymyślić prostego rozwiązania. Załóżmy, że ma łańcuchKonwertuj ciąg znaków do dyktowania za pomocą rozumienia listy w pythonie

string = "a=0 b=1 c=3" 

I do przeliczenia, że ​​w słowniku z A, B i C jest klucz i 0, 1 i 3 jest ich odpowiednie wartości (w przeliczeniu na int). Oczywiście mogę to zrobić:

list = string.split() 
    dic = {} 
    for entry in list: 
     key, val = entry.split('=') 
     dic[key] = int(val) 

Ale ja nie lubię, że dla pętli Wygląda na to tak proste, że powinieneś być w stanie przekształcić go do jakiejś wypowiedzi lista zrozumieniem. A to działa dla nieco prostszych przypadków, w których val może być ciągiem znaków.

dic = dict([entry.split('=') for entry in list]) 

Jednak muszę konwertować val do int w locie i robi coś takiego jest składniowo niepoprawne.

dic = dict([[entry[0], int(entry[1])] for entry.split('=') in list]) 

Moje pytanie brzmi: czy istnieje sposób na wyeliminowanie pętli for za pomocą zrozumienia list? Jeśli nie, czy jest jakiś wbudowany w Pythona sposób, który zrobi to dla mnie?

+0

Uwaga: Nie należy używać wbudowanych funkcji, jak nazwy zmiennych ('' list' string', etc.) –

Odpowiedz

29

Masz na myśli to?

>>> dict((n,int(v)) for n,v in (a.split('=') for a in string.split())) 
{'a': 0, 'c': 3, 'b': 1} 
+4

Mimo, że jest cool, myślę, że wolą wersję w oryginalnym pytanie od długoterminowej utrzymanie punktu widzenia kodu. Kod w pierwotnym pytaniu jest jasny i oczywisty, powyższe wymaga kilkudziesięciu sekund do zdziwienia. –

+1

@Bryan Oakley: Zgadzam się. Pytanie ("czy istnieje sposób na wyeliminowanie pętli for za pomocą zrozumienia list") ma odpowiedź. Jednak odpowiedź może nie być tym, czego naprawdę chcieli. –

+1

Tak, tego właśnie szukałem. Dziękuję Ci. @Bryan: Zaczynam myśleć, że być może utrzymanie tej pętli jest prawdopodobnie dobrym pomysłem. Niemniej przynajmniej teraz wiem, jak to zrobić w jednym wierszu. – Pavel

1
from cgi import parse_qsl 
text = "a=0 b=1 c=3" 
dic = dict((k, int(v)) for k, v in parse_qsl(text.replace(' ', '&'))) 
print dic 

drukuje

{'a': 0, 'c': 3, 'b': 1} 
+0

Nice ......... 15. –

-3

Lubię rozwiązanie S.Lott, ale wpadłem innej możliwości.
Skoro masz już napis przypominający jakoś tak, że piszesz, że można po prostu dostosować go do składni Pythona, a następnie eval() to :)

import re 
string = "a=0 b=1 c=3" 
string2 = "{"+ re.sub('(|^)(?P<id>\w+)=(?P<val>\d+)', ' "\g<id>":\g<val>,', string) +"}" 
dict = eval(string2) 
print type(string), type(string2), type(dict) 
print string, string2, dict 

regex tutaj jest dość surowy i wygrał” t wychwycić wszystkie możliwe identyfikatory Pythona, ale chciałem zachować prostotę ze względu na prostotę. Oczywiście, jeśli masz kontrolę nad tym, jak łańcuch wejściowy jest generowany, po prostu wygeneruj go zgodnie ze składnią pythona i usuń go. ALE oczywiście powinieneś wykonać dodatkowe testy poprawności, aby upewnić się, że żaden kod nie jest tam wstrzykiwany!

+2

chcesz zachować to proste? nie być wrednym czy wybierać kogokolwiek, ale gdzie jest to takie proste? – Nope

3

Co powiecie na jednolinijkowy bez rozumienia listy?

foo="a=0 b=1 c=3" 
ans=eval('dict(%s)'%foo.replace(' ',','))) 
print ans 
{'a': 0, 'c': 3, 'b': 1} 
+0

Wiem, jak działa eval, ale mam problem ze zrozumieniem tego – Ajay

+1

Foo.replace() zamienia "a = 0 b = 1 c = 3" na "a = 0, b = 1, c = 3". Formatowanie ciągów znaków tworzy nowy ciąg "dict (a = 0, b = 1, c = 3)". Eval'ing ten ciąg tworzy pożądany dict. –

+0

Zajęło mi trochę czasu, aby zrozumieć .. – Ajay

3

Spróbuj następny:

dict([x.split('=') for x in s.split()]) 
+1

OP chciał drugi element listy odrzucić do liczby całkowitej. – hughdbrown

2

czasami jak tego podejścia, zwłaszcza gdy logika dokonywania klucze i wartości jest bardziej skomplikowana:

s = "a=0 b=1 c=3" 

def get_key_val(x): 
    a,b = x.split('=') 
    return a,int(b) 

ans = dict(map(get_key_val,s.split())) 
0

Chciałbym to zrobić:

def kv(e): return (e[0], int(e[1])) 
d = dict([kv(e.split("=")) for e in string.split(" ")]) 
2

W dzisiejszych czasach hould prawdopodobnie używać słownika zrozumieniem, wprowadzone w 2.7:

mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())} 

Słownik Rozumienie jest szybsze i bardziej błyszczące (i, moim zdaniem, bardziej czytelny).

from timeit import timeit 

setup = """mystring = "a=0 b=1 c=3\"""" 
code1 = """mydict = dict((n,int(v)) for n,v in (a.split('=') for a in mystring.split()))""" # S.Lott's code 
code2 = """mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())}""" 

print timeit(code1, setup=setup, number=10000) # 0.115524053574 
print timeit(code2, setup=setup, number=10000) # 0.105328798294