python 合并两个字典列表,在所有字典中使用共享键

mxg2im7a  于 2022-12-25  发布在  Python
关注(0)|答案(2)|浏览(148)

我有两本字典:

# shop_qs
[{'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')}, {'month': 'Aug', 'sales': 2, 'revenue': Decimal('525')}]
# com_qs
[{'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')}, {'month': 'Aug', 'sales': 1, 'revenue': Decimal('450')}]

我尝试按月份合并两个列表中的字典,然后将该月份的sales字段中的值和revenue字段中的值相加。
这就是我所试图追求的,但是,正如你所看到的,产生的结果远没有接近所期望的。

total_chained_ls = list(chain(shop_qs, com_qs))
total_ls = defaultdict(int)
for d in total_chained_ls:
    for k, v in d.items():
        if isinstance(v, int) or isinstance(v, decimal.Decimal):
            total_ls[k] = total_ls[k] + v
        else:
            total_ls[k] = v

# defaultdict(<class 'int'>, {'month': 'Aug', 'sales': 5, 'revenue': Decimal('1355')})

这是所需的输出:

[{'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')}, {'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')}, {'month': 'Aug', 'sales': 3, 'revenue': Decimal('975')}]

在Python中,您将如何着手进行此操作?

  • 注意:字段中的Decimal值的作用类似于普通整数。*
9rnv2umw

9rnv2umw1#

看看这是否能帮助您:

from decimal import *
# shop_qs
lst_1 = [{'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')}, {'month': 'Aug', 'sales': 2, 'revenue': Decimal('525')}]
# com_qs
lst_2 = [{'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')}, {'month': 'Aug', 'sales': 1, 'revenue': Decimal('450')}]
# ------------------------------------------------------------------------------------------------------------------------
#   merge list_2 into list_1
for x in lst_2:
    lst_1.append(x)
#   define months of year
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

#   loop months to do the job
lst = []
lst_done = []
for month in months:
    dct = {}
    for d in lst_1:
        # check the month to decide if it should be processed or not
        if d['month'] == month and month not in lst_done: 
            sales = 0
            revenue = 0
            # calculate sums
            if month not in dct.keys():
                sales_list = [ lst_1[j]['sales'] for j in range(len(lst_1)) if lst_1[j]['month'] == month ]
                for x in sales_list:
                    sales += x
                revenue_list = [ lst_1[j]['revenue'] for j in range(len(lst_1)) if lst_1[j]['month'] == month ]
                for x in revenue_list:
                    revenue += x
                # fill in the dictionary for the month and append it to lst     
                dct['month'] = month
                dct['sales'] = sales
                dct['revenue'] = revenue
                lst.append(dct)
            # putting the month into the done list
            lst_done.append(month)
'''     R e s u l t i n g   l i s t:   (lst)
[
    {'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')}, 
    {'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')}, 
    {'month': 'Aug', 'sales': 3, 'revenue': Decimal('975')}
]
'''
hc2pp10m

hc2pp10m2#

您正确地应用了chain()来合并列表,但是您不应该将返回的迭代器消耗到列表中,因为它会将整个表达式转换为shop_qs + com_qs。由于您有静态键需要求和,因此您不需要初始化内部循环来迭代每个字典中的对,而只需要手动求和。通过某些编辑,您的代码可以转换为:

from decimal import Decimal
from itertools import chain

shop_qs = [
    {'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')},
    {'month': 'Aug', 'sales': 2, 'revenue': Decimal('525')}
]
com_qs = [
    {'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')},
    {'month': 'Aug', 'sales': 1, 'revenue': Decimal('450')}
]

total_ls = {}
for d in chain(shop_qs, com_qs):
    month = d.pop('month')
    item = total_ls.get(month)
    if item:
        item['sales'] += d['sales']
        item['revenue'] += d['revenue']
    else:
        total_ls[month] = d
  • 重要提示:dict.pop()将同时修改shop_qscom_qs的项目。*

执行后,您的total_ls将具有以下格式的数据:

{
    'Jul': {
        'sales': 1,
        'revenue': Decimal('180')
    }, 
    'Aug': {
        'sales': 3,
        'revenue': Decimal('975')
    },
    'Jun': {
        'sales': 1,
        'revenue': Decimal('200')
    }
}

你可以使用next list comprehension把它转换回字典列表:

[{'month': k} | v for k, v in total_ls.items()]
# OR (for older python versions)
[{'month': k, **v} for k, v in total_ls.items()]

另一种按特定条件合并项的方法是对排序后的数据使用groupby()

from decimal import Decimal
from itertools import chain, groupby
from operator import itemgetter

shop_qs = [
    {'month': 'Jul', 'sales': 1, 'revenue': Decimal('180')},
    {'month': 'Aug', 'sales': 2, 'revenue': Decimal('525')}
]
com_qs = [
    {'month': 'Jun', 'sales': 1, 'revenue': Decimal('200')},
    {'month': 'Aug', 'sales': 1, 'revenue': Decimal('450')}
]

month_getter = itemgetter('month')
sorted_chained_ls = sorted(chain(shop_qs, com_qs), key=month_getter)
total_ls = []
for _, group in groupby(sorted_chained_ls, month_getter):
    item = next(group)
    total_ls.append(item)
    for i in group:
        item['sales'] += i['sales']
        item['revenue'] += i['revenue']

相关问题