2014-01-19 3 views
1

У меня есть список однокамерных словарей. Например:Python - конвертировать список одно ключевых словарей в один словарь

lst = [ 
    {'1': 'A'}, 
    {'2': 'B'}, 
    {'3': 'C'} 
] 

Я хотел бы просто преобразовать это в нормальный словарь:

dictionary = { 
    '1': 'A', 
    '2': 'B', 
    '3': 'C' 
} 

Что наиболее лаконичным/эффективный способ сделать это?

ответ

10

Вы можете использовать уменьшить:

reduce(lambda r, d: r.update(d) or r, lst, {}) 

Демо:

>>> lst = [ 
...  {'1': 'A'}, 
...  {'2': 'B'}, 
...  {'3': 'C'} 
... ] 
>>> reduce(lambda r, d: r.update(d) or r, lst, {}) 
{'1': 'A', '3': 'C', '2': 'B'} 

или вы могли бы цепь элементы вызовов (Python 2):

from itertools import chain, imap 
from operator import methodcaller 

dict(chain.from_iterable(imap(methodcaller('iteritems'), lst))) 

Python 3 версии:

from itertools import chain 
from operator import methodcaller 

dict(chain.from_iterable(map(methodcaller('items'), lst))) 

Демо:

>>> from itertools import chain, imap 
>>> from operator import methodcaller 
>>> 
>>> dict(chain.from_iterable(map(methodcaller('iteritems'), lst))) 
{'1': 'A', '3': 'C', '2': 'B'} 

Или использовать Dict понимание:

{k: v for d in lst for k, v in d.iteritems()} 

Демо:

>>> {k: v for d in lst for k, v in d.iteritems()} 
{'1': 'A', '3': 'C', '2': 'B'} 

Из трех, для простого 3-словаря входа, ДИКТ понимание является быстрая:

>>> import timeit 
>>> def d_reduce(lst): 
...  reduce(lambda r, d: r.update(d) or r, lst, {}) 
... 
>>> def d_chain(lst): 
...  dict(chain.from_iterable(imap(methodcaller('iteritems'), lst))) 
... 
>>> def d_comp(lst): 
...  {k: v for d in lst for k, v in d.iteritems()} 
... 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_reduce as f') 
2.4552760124206543 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_chain as f') 
3.9764280319213867 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_comp as f') 
1.8335261344909668 

Когда вы увеличить количество элементов в inputlist до 1000, то метод chain догоняет:

>>> import string, random 
>>> lst = [{random.choice(string.printable): random.randrange(100)} for _ in range(1000)] 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_reduce as f', number=10000) 
5.420135974884033 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_chain as f', number=10000) 
3.464245080947876 
>>> timeit.timeit('f(lst)', 'from __main__ import lst, d_comp as f', number=10000) 
3.877490997314453 

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

+0

Черт! Вы избили меня до этого, пока я публиковал демо: – inspectorG4dget

+0

У вас есть все это в виду? : O: P –

1
answer = {} 
for d in L: 
    answer.update(d) 

Выход:

>>> L = [ 
...  {'1': 'A'}, 
...  {'2': 'B'}, 
...  {'3': 'C'} 
... ] 
>>> answer = {} 
>>> for d in L: answer.update(d) 
... 
>>> answer 
{'2': 'B', '3': 'C', '1': 'A'} 

ИЛИ

answer = {k:v for d in L for k,v in d.items()} 
6

Вы можете использовать dictionary comprehension:

>>> lst = [ 
...  {'1': 'A'}, 
...  {'2': 'B'}, 
...  {'3': 'C'} 
... ] 
>>> {k:v for x in lst for k,v in x.items()} 
{'2': 'B', '3': 'C', '1': 'A'} 
>>> 
+1

Я думаю, что это самый простой и простой. – tayfun

+0

Это решение работает для python3, для python2 вы должны использовать x.iteritems() –

Смежные вопросы