【问题标题】:Combine several dictionaries based on a common key value into one dictionary基于一个公共键值的多个字典组合成一个字典
【发布时间】:2016-12-07 14:54:49
【问题描述】:

基本上我有一个 OrderedDicts 列表;

lst = [
    OrderedDict([('type', 'character'), ('letter', 'a')]),
    OrderedDict([('type', 'character'), ('letter', 'b')]),
    OrderedDict([('type', 'character'), ('letter', 'c')]),
    OrderedDict([('type', 'character'), ('letter', 'd')]),
    OrderedDict([('type', 'integer'), ('number', '1')]),
    OrderedDict([('type', 'integer'), ('number', '2')]),
    OrderedDict([('type', 'integer'), ('number', '3')]),
    OrderedDict([('type', 'integer'), ('number', '4')])
]

我想改成

lst = [
    OrderedDict([('type', 'character'), ('letter', ['a', 'b', 'c', 'd'])]),
    OrderedDict([('type', 'integer'), ('number', ['1', '2', '3', '4'])])
]

我想有一个类型值列表 ['character', 'integer'] 并浏览所有字典以尝试将字母/数字分组到一个列表中,然后创建一个要填写的新字典列表我得到的数据。不确定这是否是最好的方法

感谢帮助

【问题讨论】:

    标签: python dictionary merge


    【解决方案1】:

    考虑到您的词典列表已经排序,您可以直接使用itertools.groupby。字典中项目及其相关字符串之间的映射有助于避免多次调用d.items,并使代码可扩展为新类型:

    from collections import OrderedDict
    from itertools import groupby
    
    _map = {'character': 'letter', 'integer': 'number'}
    
    l = [OrderedDict([('type', k), (_map[k], [d[_map[k]] for d in g])]) for k, g in groupby(lst, lambda x: x['type'])]
    print(l)
    # [OrderedDict([('type', 'character'), ('letter', ['a', 'b', 'c', 'd'])]), OrderedDict([('type', 'integer'), ('number', ['1', '2', '3', '4'])])]
    

    【讨论】:

      【解决方案2】:

      应该可以的:

      lst = [OrderedDict([('type', t), (kind, [d.items()[1][1] for d in lst if d['type'] == t])]) for (t, kind) in set((d['type'], d.items()[1][0]) for d in lst)]
      

      输出:

      [OrderedDict([('type', 'integer'), ('number', ['1', '2', '3', '4'])]), OrderedDict([('type', 'character'), ('letter', ['a', 'b', 'c', 'd'])])]
      

      【讨论】:

        【解决方案3】:

        对于列表理解较少的答案(这有助于 有时可读性。)请参阅:

        from collections import OrderedDict
        
        lst = [
            OrderedDict([('type', 'character'), ('letter', 'a')]),
            OrderedDict([('type', 'character'), ('letter', 'b')]),
            OrderedDict([('type', 'character'), ('letter', 'c')]),
            OrderedDict([('type', 'character'), ('letter', 'd')]),
            OrderedDict([('type', 'integer'), ('number', '1')]),
            OrderedDict([('type', 'integer'), ('number', '2')]),
            OrderedDict([('type', 'integer'), ('number', '3')]),
            OrderedDict([('type', 'integer'), ('number', '4')])
        ]
        
        types_found = []  # using a list to maintain original order
        types_dict = {}   # using a dict for speed and storage
        
        for entry in lst:
            t = entry.get("type", "unknown")
            if t not in types_dict:
                types_found.append(t)
                types_dict[t] = OrderedDict([("type", t)])
            for k, v in entry.items():
                if k != "type":
                    types_dict[t].setdefault(k, []).append(v)
        
        new_list = [types_dict[t] for t in types_found]
        # okay, so I did use one list comprehension, but it's a simple one :)
        

        对于上述内容,我假设以下内容很重要:

        • 除了“字符”或“整数”之外,您可能还有其他“类型”条目;所以你想要一个开放式的解决方案。
        • 您希望保留在 lst 中找到的原始订单。
        • 您的生产代码可能缺少密钥;或比预期更多的键。

        这是用 Python 3.5 编写的。对于某些旧版本,您可能需要将 '.items()' 替换为 '.iteritems()'。

        【讨论】:

        • 回想起来,如果将 types_dict 设置为 OrderedDict() 而不是普通字典,我可以删除 types_found 跟踪以维护订单。某种意义上的讽刺。
        猜你喜欢
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-29
        • 1970-01-01
        • 2012-09-19
        • 1970-01-01
        • 2018-11-14
        相关资源
        最近更新 更多