2013-08-09 4 views
0

У меня есть строка:Преобразование Python строки в словарь

A = "{user_id:34dd833,category:secondary,items:camera,type:sg_ser}" 

Мне нужно, чтобы преобразовать его в словарь питона, так что:

A = {"user_id":"34dd833", "category": "secondary", "items": "camera", "type": "sg_ser"} 

Кроме того, есть еще два вопроса:

1: ключ "элементы", как предполагается, имеют несколько значений, например:

A = {"user_id":34dd833, "category": "secondary", "items": "camera,vcr,dvd", "type": "sg_ser"} 

Который, видимо, приходит в виде строки, как:

A = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}" 

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

2: Порядок строки может быть случайным. Таким образом, строка может быть, как это так:

A = "{category:secondary,type:sg_ser,user_id:34dd833,items:camera,vcr,dvd}" 

Что делает любой процесс, предположив редеют по заказу как ложный.

Что делать в такой ситуации? Большое спасибо.

+0

Какая ценности в том, что '34dd833' в предполагаемом выходе? Вы хотели поставить это в кавычки? Или префикс с 0x? Или что-то другое? – abarnert

+0

ohh .. Извините .. это должна быть строка .. мне мне нужно изменить вопрос. – user2480542

+2

Почему ваш ввод выглядит так? От куда это? Я почти уверен, что это недействительно JSON. – user2357112

ответ

7

Если мы можем предположить, что ваш ввод не выполняет никаких кавычек или экранирования (ваш пример не делает этого, но это не обязательно означает, что это хорошее предположение), и что вы никогда не сможете разделить запятую несколько ключей, только несколько значений (которые, вероятно, является хорошее предположение, так как в противном случае формат неоднозначна ...):

Во-первых, давайте опускать скобки, затем разделить на двоеточиями:

>>> A = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}" 
>>> A[1:-1].split(':') 
['user_id', '34dd833,category', 'secondary,items', 'camera,vcr,dvd,type', 'sg_ser'] 

Так первая запись - это первый ключ, последняя запись - e последнее значение (ы), и каждая запись между ними - это N-е значение (ы), за которым следует запятая, за которой следует N + 1-й ключ. Там могут быть и другие запятые, но последний всегда разделяет N-е значение (ы) с N + 1-го ключа. (И это даже работает для N = 0 - нет никаких запятых, поэтому последняя запятая ничего не отделяет от 0-го ключа, но, к сожалению, она не работает для самой последней записи. Я доберусь до этого позже.)

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

>>> d = {} 
>>> entries = A[1:-1].split(':') 
>>> for i in range(len(entries)-1): 
...  key = entries[i].rpartition(',')[-1] 
...  value = entries[i+1].rpartition(',')[0] 
...  d[key] = value 

Это почти сразу:

>>> d 
{'category': 'secondary', 'items': 'camera,vcr,dvd', 'type': '', 'user_id': '34dd833'} 

Как уже упоминалось выше, он не работает на последней. Это должно быть очевидно, почему; если нет, посмотрите, что возвращает rpartition(',') за последнее значение. Вы можете исправить это вручную или просто обмануть, добавив дополнительно , на конец (entries = (A[1:-1] + ',').split(':')). Но если вы думаете об этом, если вы просто rsplit вместо rpartition, то [0] делает правильные вещи. Так что давайте сделаем это вместо этого.

Итак, как мы можем немного почистить это?

Сначала давайте преобразуем entries в список смежных пар. Теперь каждая из каждой пары (n, nplus1), n.rpartition(',')[-1] является ключевым, а nplus1.rsplit(',', 1)[0] - соответствующее значение. Итак:

>>> A = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}" 
>>> entries = A[1:-1].split(':') 
>>> adjpairs = zip(entries, entries[1:]) 
>>> d = {k.rpartition(',')[-1]: v.rsplit(',', 1)[0] for k, v in adjpairs} 
+2

Это должно быть 'v.rsplit (',', 1) [0]' в последней строке, иначе вы получите только «камеру» в элементах. –

+0

@PauloAlmeida: Спасибо! Обратите внимание, что я понял это в описании выше. И я тоже понял это на своем локальном ipython. И именно поэтому вы всегда должны копировать и вставлять, а затем очищать, а не очищать при копировании. :) – abarnert

+0

@abarnert Мне удалось разбить чудовище регулярного выражения, но мне это нравится;) –

2

Вот еще один способ (не особо прочный, но показывает, что это возможно по данным выборки):

import re 
text = "{user_id:34dd833,category:secondary,items:camera,vcr,dvd,type:sg_ser}" 
print dict(re.findall(r'(\w+):(.*?)(?=(?:,\w+:)|$)', text.strip('{}'))) 
# {'category': 'secondary', 'items': 'camera,vcr,dvd', 'user_id': '34dd833', 'type': 'sg_ser'} 
Смежные вопросы