преобразование строки в dict с использованием понимания списка в python

я сталкивался с этой проблемой несколько раз и, похоже, не могу найти простое решение. Скажем, у меня есть строка

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

Я хочу преобразовать это в словарь с A, b и c, являющимся ключом и 0, 1 и 3, являющимися их соответствующими значениями (преобразованными в int). Очевидно, я могу это сделать:

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

но мне это не очень нравится для цикла, это кажется настолько простым, что вы должны иметь возможность преобразовать его в какое-то выражение понимания списка. И это работает для немного более простых случаев, когда val может быть строкой.

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

однако мне нужно преобразовать val в int на лету и сделать что-то вроде этого синтаксически неверно.

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

Итак, мой вопрос: есть ли способ устранить цикл for, используя понимание списка? Если нет, есть ли какой-то встроенный метод python, который сделает это для меня?

8 ответов


вы имеете в виду это?

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

Как насчет однострочного без понимания списка?

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

попробуйте следующее:

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

Мне иногда нравится этот подход, особенно когда логика создания ключей и значений сложнее:

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()))

В настоящее время вы, вероятно, должны использовать понимание словаря, введенное в 2.7:

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

понимание словаря быстрее и ярче (и, на мой взгляд, более читаемым).

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

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

печать

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

Я бы сделал так:

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

Мне нравится решение С. Лотта, но я придумал другую возможность.
Поскольку у вас уже есть строка, похожая на то, как вы это пишете, вы можете просто адаптировать ее к синтаксису python, а затем eval () it:)

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

регулярное выражение здесь довольно сырое и не поймает все возможные идентификаторы python, но я хотел сохранить его простым для простоты. Конечно, если у вас есть контроль над тем, как генерируется входная строка, просто создайте ее в соответствии с синтаксисом python и eval его. Но конечно вы должны выполнить дополнительные проверки, чтобы убедиться, что код вводится там!