Как разбирать строку в словаре

Я пытаюсь разобрать строку для разделения списков внутри строки. У меня есть строка:

string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"

Есть ли способ разбора строки, чтобы ключ словаря был первым элементом списка, а значение ключа - рядом с элементами. Например:

{'q1': ('0','q1'), 'q1': ('1','q2'), 'q2': ('0','q2'), 'q2': ('1', 'q1')}
5 ответов

Введенный dictionary может иметь список: вы можете использовать ast.literal_eval для анализа структуры данных python из строки

>>> import ast
>>> my_string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
>>> k = ast.literal_eval(my_string)
>>> k
[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]
>>> [[x[0],tuple(x[1:])] for x in k]
[['q1', ('0', 'q1')], ['q1', ('1', 'q2')], ['q2', ('0', 'q2')], ['q2', ('1', 'q1')]]


Чтобы сохранить дубликаты и соответствовать формату ввода:

import collections
import json
string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = collections.defaultdict(list)
for (k, v1, v2) in json.loads(string.replace("'",'"')):
 d[k].append((v1, v2))

С помощью eval (если вы доверяете своему вводу):

import collections
string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = collections.defaultdict(list)
for (k, v1, v2) in eval(string):
 d[k].append((v1, v2))

Содержание d:

defaultdict(<type 'list'="">, {
 'q1': [('0', 'q1'), ('1', 'q2')],
 'q2': [('0', 'q2'), ('1', 'q1')]
})
</type>

EDIT: и без библиотеки вообще.

string = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"
d = {}
for (k, v1, v2) in eval(string):
 d.setdefault(k, []).append((v1, v2))

Я не могу сделать это одним лайнером, хотя :-)


Вы можете использовать JSON, но строковый формат должен быть dict, и вы не можете иметь 2 раза один и тот же ключ:

import json

string ='{"q": ["0", "q1"], "q1": ["1", "q2"], "q3": ["1", "q1"], "q2": ["0", "q2"]}'

dict = json.loads(string)

print dict
Output: {'q': ['0', 'q1'], 'q1': ['1', 'q2'], 'q3': ['1', 'q1'], 'q2': ['0', 'q2']}


Вы можете получить вложенные словари из вашей строки (немного менее прямолинейные, чем предыдущие ответы). Благодаря Alex Martelli за его ответ на обновление значения вложенного словаря различной глубины

import ast

def update(d, u):
 for k, v in u.iteritems():
 if isinstance(v, dict):
 r = update(d.get(k, {}), v)
 d[k] = r
 else:
 d[k] = u[k]
 return d

def listToDict(l):
 temp = l[-1]
 for value in l[-2::-1]:
 temp = {value: temp}
 return temp

input = "[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]"

res = {}
for l in ast.literal_eval(input):
 update(res ,listToDict(l))
print res

Вывод:

{'q1': {'1': 'q2', '0': 'q1'}, 'q2': {'1': 'q1', '0': 'q2'}}


попробуй это

>>> import ast
>>> ast.literal_eval(string)
[['q1', '0', 'q1'], ['q1', '1', 'q2'], ['q2', '0', 'q2'], ['q2', '1', 'q1']]
>>> list=ast.literal_eval(string)
>>> d={}
>>> for l in list:
... d[l[0]]=tuple(l[1:])
>>> d
{'q1': ('1', 'q2'), 'q2': ('1', 'q1')}

ключ всегда уникален в dict, поэтому в результате отображается обновленная пара значений ключа

licensed under cc by-sa 3.0 with attribution.