【问题标题】:Convert list of single key dictionaries into a single dictionary将单键字典列表转换为单个字典
【发布时间】:2014-01-19 21:25:34
【问题描述】:

我有一个单键字典列表。例如:

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

我想简单地将其转换为普通字典:

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

最简洁/最有效的方法是什么?

【问题讨论】:

    标签: python list dictionary


    【解决方案1】:

    你可以使用reduce:

    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'}
    

    或者使用字典推导:

    {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-dictionary输入,dict理解最快:

    >>> 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
    

    当您增加输入列表中的项目数到 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() 方法速度快了一小部分,但从未获得明显优势。

    【讨论】:

      【解决方案2】:

      您可以使用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'}
      >>>
      

      【讨论】:

      • 这个解决方案适用于python3,对于python2你应该使用x.iteritems()
      【解决方案3】:
      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()}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-09
        • 1970-01-01
        • 1970-01-01
        • 2021-08-20
        • 2018-08-21
        • 1970-01-01
        • 1970-01-01
        • 2021-09-09
        相关资源
        最近更新 更多