2010-11-20 6 views
6

У меня есть несколько словарей с разными и общими ключами, а также разные и общие ключи во вложенном словаре. Ниже приведен упрощенный пример, в словарях есть тысячи ключей.Объединить вложенные словари, вложенные ключи?

{1:{"Title":"Chrome","Author":"Google","URL":"http://"}} 
{1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}} 
{2:{"Title":"Python","Version":"2.5"}} 

Что я хотел бы объединить в один словарь.

{1:{"Title":"Chrome","Author":"Google","URL":"http://","Version":"7.0.577.0"}, 
2:{"Title":"Python","Version":"2.5"}} 

Я могу перебрать обоих словарей, сравнить ключи и update вложенных словарей, но, вероятно, является более эффективным, или вещий, способ сделать это. Если нет, то что наиболее эффективно?

Значения вложенного словаря не нужно сравнивать.

+0

Если вы действительно отображение последовательных целочисленных ключей, это не имело бы больше смысла производить список в качестве результата? –

+0

Здесь много обсуждений и советов: http://stackoverflow.com/questions/38987/how-can-i-merge-two-python-dictionaries-as-a-single-expression – mjhm

+0

Кажется очень нереалистичным, что каждый из у «нескольких словарей» есть ровно одна пара ключ/значение в нем - заставляет задуматься, почему они - словари вообще, когда простой кортеж или список с двумя элементами в нем будут работать так же хорошо. – martineau

ответ

5
from collections import defaultdict 

mydicts = [ 
    {1:{"Title":"Chrome","Author":"Google","URL":"http://"}}, 
    {1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}}, 
    {2:{"Title":"Python","Version":"2.5"}}, 
] 

result = defaultdict(dict) 

for d in mydicts: 
    for k, v in d.iteritems(): 
     result[k].update(v) 

print result 

defaultdict(<type 'dict'>, 
    {1: {'Version': '7.0.577.0', 'Title': 'Chrome', 
     'URL': 'http://', 'Author': 'Google'}, 
    2: {'Version': '2.5', 'Title': 'Python'}}) 
+0

Незначительная настройка: второй 'for' может быть заменен на' k, v = next (d.iteritems()) 'и следующую разделительную строку. Не очень большая разница, но это будет выглядеть быстрее. ;-) – martineau

+0

@martineau: он также выглядел бы менее полезным: 'next()' работает только на python 2.6+. Также способ, которым я написал, допускает более одного ключа на каждом 'dict' или пустом' dict', не задыхаясь или делающего неправильную вещь – nosklo

+0

Ну, вы правы в том, что 'next()' не был доступен до v2.6 - - когда я писал это, я забыл, что OP хочет использовать совместимое с v2.5 решение. Однако можно утверждать, что желательно принять неверно сформированные вложенные 'dict' с более чем одним ключом, и, наконец, 'next()' может обрабатывать пустые 'dict' без проблем. С учетом всех вещей, я по-прежнему считаю, что мой комментарий является правильным наблюдением для тех, кто там использует, по крайней мере, v2.6 Python. – martineau

2

Из вашего примера, выглядит, как вы можете сделать что-то вроде:

from collections import defaultdict 
mydict = defaultdict(dict) 
for indict in listofdicts: 
    k, v = indict.popitem() 
    mydict[k].update(v) 
Смежные вопросы