求和字典值,使用两个键作为索引:如何实现?
Sum dictionary values, using two keys as index: how to achieve this?
我有以下词典:
res = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1500.0, 'tax_amount': 210.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1000.0, 'tax_amount': 0.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 900.0, 'tax_amount': 126.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]
从这本词典中,我需要对 'tax_base' 和 'tax_amount' 值键求和,并使用键 'name' 和 'percentage' 作为索引。
因此,我需要:
res_final = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0},
]
我怎样才能做到这一点?可以给我样品吗?
采用您的原始输入 res
和您的首选输出 res_final
,以下代码将起作用:
# Creating a temporary dictionary with the aggregation
temp_result = {}
for each in res:
key = (each['name'], each['percentage'])
if key not in temp_result:
temp_result[key] = dict(tax_base=0, tax_amount=0)
temp_result[key]['tax_base'] += each['tax_base']
temp_result[key]['tax_amount'] += each['tax_amount']
# Transforming the temporary dictionary to the correct format
final_result = []
for (name, percentage), taxes in temp_result.items():
final_result.append(dict(
name=name,
percentage=percentage,
tax_base=taxes['tax_base'],
tax_amount=taxes['tax_amount']
))
for each in final_result:
print(each)
结果将是:
{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0}
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0}
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0}
说明
在第一部分中,我们创建了一个新字典,它的键是 name
和 percentage
的组合作为 tuple
,值是一个字典 tax_base
和 tax_amount
对应那个键。
然后我们检查键是否已经在我们的字典中,如果不在我们创建键。最后一步是对 tax_base
和 tax_amount
.
求和
现在我们有了一本包含所有信息的字典,但格式不正确。第二部分负责这一点。我们再次将密钥拆分为 name
和 percentage
并将数据与 tax_base
和 tax_amount
合并到一个字典中。
编辑
以防人们想知道如何使用 pd.DataFrame
。
import pandas as pd
df = pd.DataFrame(res)
res = df.groupby(['name', 'percentage'], as_index=False).sum()
final_result = res.to_dict('records')
for each in final_result:
print(each)
将产生相同的输出,但不保证与输入的顺序相同。
这是另一种(非常相似)的方法,但更加简洁。
在这里,我们首先创建一个唯一 name:percentage
对列表,然后遍历这些唯一键,从 res
列表中过滤掉与该唯一键不匹配的条目。
unique_keys = list(set([f"{d['name']}:{d['percentage']}" for d in res])) # use list(set()) to keep only unique values as keys
output = []
for key in unique_keys:
name, percentage = key.split(":")
matching_entries = list(filter(lambda d: d['name'] == name and str(d['percentage']) == percentage, res))
summed = {"name": name, "percentage": float(percentage), "tax_base": 0.0, "tax_amount": 0.0}
for entry in matching_entries:
summed["tax_base"] += entry.get("tax_base", 0) # use get in case value is not in dictionary, 0 is default value
summed["tax_amount"] += entry.get("tax_amount", 0)
output.append(summed)
output.sort(key=lambda d: d['name']) # sorting to organize a bit
输出:
[{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]
我有以下词典:
res = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1500.0, 'tax_amount': 210.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1000.0, 'tax_amount': 0.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 900.0, 'tax_amount': 126.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]
从这本词典中,我需要对 'tax_base' 和 'tax_amount' 值键求和,并使用键 'name' 和 'percentage' 作为索引。
因此,我需要:
res_final = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0},
]
我怎样才能做到这一点?可以给我样品吗?
采用您的原始输入 res
和您的首选输出 res_final
,以下代码将起作用:
# Creating a temporary dictionary with the aggregation
temp_result = {}
for each in res:
key = (each['name'], each['percentage'])
if key not in temp_result:
temp_result[key] = dict(tax_base=0, tax_amount=0)
temp_result[key]['tax_base'] += each['tax_base']
temp_result[key]['tax_amount'] += each['tax_amount']
# Transforming the temporary dictionary to the correct format
final_result = []
for (name, percentage), taxes in temp_result.items():
final_result.append(dict(
name=name,
percentage=percentage,
tax_base=taxes['tax_base'],
tax_amount=taxes['tax_amount']
))
for each in final_result:
print(each)
结果将是:
{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0}
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0}
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0}
说明
在第一部分中,我们创建了一个新字典,它的键是 name
和 percentage
的组合作为 tuple
,值是一个字典 tax_base
和 tax_amount
对应那个键。
然后我们检查键是否已经在我们的字典中,如果不在我们创建键。最后一步是对 tax_base
和 tax_amount
.
现在我们有了一本包含所有信息的字典,但格式不正确。第二部分负责这一点。我们再次将密钥拆分为 name
和 percentage
并将数据与 tax_base
和 tax_amount
合并到一个字典中。
编辑
以防人们想知道如何使用 pd.DataFrame
。
import pandas as pd
df = pd.DataFrame(res)
res = df.groupby(['name', 'percentage'], as_index=False).sum()
final_result = res.to_dict('records')
for each in final_result:
print(each)
将产生相同的输出,但不保证与输入的顺序相同。
这是另一种(非常相似)的方法,但更加简洁。
在这里,我们首先创建一个唯一 name:percentage
对列表,然后遍历这些唯一键,从 res
列表中过滤掉与该唯一键不匹配的条目。
unique_keys = list(set([f"{d['name']}:{d['percentage']}" for d in res])) # use list(set()) to keep only unique values as keys
output = []
for key in unique_keys:
name, percentage = key.split(":")
matching_entries = list(filter(lambda d: d['name'] == name and str(d['percentage']) == percentage, res))
summed = {"name": name, "percentage": float(percentage), "tax_base": 0.0, "tax_amount": 0.0}
for entry in matching_entries:
summed["tax_base"] += entry.get("tax_base", 0) # use get in case value is not in dictionary, 0 is default value
summed["tax_amount"] += entry.get("tax_amount", 0)
output.append(summed)
output.sort(key=lambda d: d['name']) # sorting to organize a bit
输出:
[{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0},
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]