Создание многоуровневого словаря из строки [Python] - PullRequest
2 голосов
/ 06 февраля 2012

Я создаю почтового «бота» для одного из моих веб-сервисов, который будет периодически собирать очередь сообщений электронной почты, которые будут отправлены из сценария PHP, и отправлять их через SMTP-серверы Google. Скрипт PHP возвращает сообщения в следующем формате:

test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar

Мне нужно «преобразовать» что-то вроде этого:

{
    "test@example.com": [
        [
            "Full Name",
            "shortname"
        ],
        [
            "Foo",
            "bar"
        ]
    ],
    "test2@example.com": [
        [
            "Another Full Name",
            "anothershortname"
        ]
    ]
}

Обратите внимание: мне нужно иметь только один ключ для электронной почты, даже если есть несколько экземпляров адреса. Я знаю, что, вероятно, я могу сделать это с двумя последовательными циклами, один для создания первого уровня словаря и второй для его заполнения, но должен быть способ сделать это за один раз. Это мой код:

raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"

print raw

newlines = raw.split("\n")

print newlines

merged = {}
for message in newlines:
    message = message.split(":")
    merged[message[0]].append([message[1], message[2]])

print merged

Я получаю сообщение об ошибке KeyError в последней строке цикла, которое, как я понимаю, означает, что ключ должен существовать до добавления чего-либо к нему (добавление к несуществующему ключу не создаст этот ключ).

Я новичок в Python и пока не очень знаком со списками и словарями, поэтому ваша помощь очень ценится!

Ответы [ 4 ]

1 голос
/ 06 февраля 2012

Я вижу, что вы уже приняли ответ, но, возможно, вам все равно интересно, что то, что вы делаете, может быть легко достигнуто с помощью defaultdict:

from collections import defaultdict
raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"

merged = defaultdict(list)
for line in raw.split('\n'):
    line = line.split(':')
    merged[line[0]].append(line[1:])
1 голос
/ 06 февраля 2012

Вы правы насчет ошибки.Таким образом, вы должны проверить, если ключ присутствует.'key' in dict возвращает True, если 'key' найдено в dict, в противном случае False.Реализуя это, вот ваш полный код (с удаленными отладочными операторами печати):

raw = "test@example.com:Full Name:shortname\ntest2@example.com:Another Full Name:anothershortname\ntest@example.com:Foo:bar"
newlines = raw.split("\n")
merged = {}
for message in newlines:
    message = message.split(":")
    if message[0] in merged:
        merged[message[0]].append([message[1], message[2]])
    else:
        merged[message[0]]=[[message[1], message[2]]]    
print merged

Обратите внимание на дополнительные скобки для вложенного списка во второй последней строке.

1 голос
/ 06 февраля 2012

Может работать как:

for message in newlines:
    message = message.split(":")
    temp = []
    temp.append(message[1])
    temp.append(message[2])
    merged[message[0]] = temp

На самом деле может быть:

for message in newlines:
    message = message.split(":")
    temp = []
    temp.append(message[1])
    temp.append(message[2])
    if message[0] not in merged:
        merged[message[0]] = []
    merged[message[0]].append(temp)
0 голосов
/ 06 февраля 2012

Просто проверьте наличие ключа, если его нет, создайте ключ, если он присутствует, добавьте данные в существующий список.

if(messsage[0] in merged):
     merged[message[0]] = [message[1],[message[2]]
else:
     merged[message[0]].append([[message[1], message[2]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...