【问题标题】:Merge dict in a Python list在 Python 列表中合并字典
【发布时间】:2021-06-09 15:20:04
【问题描述】:

假设我有这个:

[
    {"name": "bob", "total": 1},
    {"name": "alice", "total": 5},
    {"name": "eve", "total": 2},
    {"name": "bob", "total": 3},
    {"name": "alice", "total": 2},
    {"name": "alice", "total": 2},
]

我想将此列表转换为:

[
    {"name": "bob", "total": 4},
    {"name": "alice", "total": 9},
    {"name": "eve", "total": 2}
]

现在,我遍历整个第二个列表以查找第一个列表的每个循环的键是否存在。

如何以较低的复杂性实现这一目标?

【问题讨论】:

标签: python list dictionary


【解决方案1】:
from collections import defaultdict

a = [
    {"name": "bob", "total": 1},
    {"name": "alice", "total": 5},
    {"name": "eve", "total": 2},
    {"name": "bob", "total": 3},
    {"name": "alice", "total": 2},
    {"name": "alice", "total": 2},
]

# calculate the frequency of each key
freq = defaultdict(lambda: 0)
for d in a:
    freq[d['name']] += d['total']

# build the result list
a = list()
for key, val in freq.items():
    a.append({'name': key, 'total': val})
print(a)

【讨论】:

    【解决方案2】:

    如果您只有两条信息(姓名和总数),我建议您稍微更改一下您的架构。而不是字典列表,而是使用单个字典,其中键是名称,值是总数:

    >>> values = [
    ...     {"name": "bob", "total": 1},
    ...     {"name": "alice", "total": 5},
    ...     {"name": "eve", "total": 2},
    ...     {"name": "bob", "total": 3},
    ...     {"name": "alice", "total": 2},
    ...     {"name": "alice", "total": 2},
    ... ]
    >>> from collections import defaultdict
    >>> totals_by_name = defaultdict(int)
    >>> for value in values:
    ...     totals_by_name[value["name"]] += value["total"]
    ... 
    >>> totals_by_name
    defaultdict(<class 'int'>, {'bob': 4, 'alice': 9, 'eve': 2})
    

    即使您有更多要按名称查找的数据也可以使用(将整数值替换为存储总数和其他数据的嵌套字典)。

    【讨论】:

    • 是的,最好清理架构。但由于它是 API 输出,我无法更改输出。
    【解决方案3】:

    您可以使用itertools 模块中的groupby

    from itertools import groupby
    from operator import itemgetter
    
    # itemgetter(foo) is roughly equivalent to lambda x: x[foo]
    get_name = itemgetter('name')
    get_total = itemgetter('total')
    
    lst = [
        {"name": "bob", "total": 1},
        {"name": "alice", "total": 5},
        {"name": "eve", "total": 2},
        {"name": "bob", "total": 3},
        {"name": "alice", "total": 2},
        {"name": "alice", "total": 2},
    ]
    grouped = groupby(sorted(lst, key=get_name), get_name)
    new_list = [{'name': k, 'total': sum(get_total(x) for x in v)} for k, v in grouped]
    

    groupby 将根据'name' 属性的公共值生成一个新序列,该序列将原始列表中的字典收集到子序列中。对其进行迭代,您可以提取所有 total 值以汇总以用于新的 dict 值列表。

    【讨论】:

      【解决方案4】:

      比方说,

      your_data = [
          {"name": "bob", "total": 1},
          {"name": "alice", "total": 5},
          {"name": "eve", "total": 2},
          {"name": "bob", "total": 3},
          {"name": "alice", "total": 2},
          {"name": "alice", "total": 2},
      ]
      

      您可以简单地使用 pandas 来接收所需的输出。

      import pandas as pd
      
      df = pd.DataFrame(your_data)    
      df = df.groupby(by = 'name', as_index = False).sum('total')
      result = df.to_dict(orient = 'records')
      

      输出: [{'name': 'alice', 'total': 9}, {'name': 'bob', 'total': 4}, {'name': “前夕”,“总计”:2}]

      【讨论】:

        猜你喜欢
        • 2012-08-11
        • 2012-07-17
        • 2015-01-10
        • 2021-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多