我有以下字典:
CostofA = {'Cost1,(1, 2)': 850.93,
'Cost1,(1, 2, 3)': 851.08,
'Cost1,(1, 3)': 851.00,
'Cost1,(1,)': 850.86,
'Cost2,(1, 2)': 812.56,
'Cost2,(1, 2, 3)': 812.65,
'Cost2,(2, 3)': 812.12,
'Cost2,(2,)': 812.04,
'Cost3,(1, 2, 3)': 717.93,
'Cost3,(1, 3)': 717.88,
'Cost3,(2, 3)': 717.32,
'Cost3,(3,)': 717.27}
从这本词典中,我想通过添加具有类似键的元素来创建以下词典。例如,我想将'Cost1,(1, 2, 3)'
,'Cost2,(1, 2, 3)'
和'Cost3,(1, 2, 3)'
的值相加,因为它们在括号(1, 2, 3)
内具有相同的数字并创建'Cost(1, 2, 3)': 2381.66
。同样,'Cost1,(1, 3)'
和'Cost3,(1, 3)'
括号内的数字相同,因此,我想将851.00
和717.88
相加并将其写入我的新字典:{{1 }}。对于'Cost(1, 3)': 1568.88
,'Cost1,(1,)'
和'Cost2,(2,)'
,除了将它们添加到新词典之外,我不想做任何事情。如果我可以在括号中的1之后立即删除逗号,那将是完美的。所以,我的意思是:'Cost3,(3,)'
变为'Cost1,(1,)': 850.86
。
'Cost(1)': 850.86
我知道我可以通过
到达字典的键CostofA = {'Cost(1)': 850.86,
'Cost(2)': 812.04,
'Cost(3)': 717.27,
'Cost(1, 2)': 1663.58,
'Cost(1, 3)': 1568.88,
'Cost(2, 3)': 1529.34,
'Cost(1, 2, 3)': 2381.66}
我知道我可以创建一个带有for循环和if条件的逻辑来创建上面的字典,但是,我想不出一种方法来达到if语句中括号内的数字。有什么建议吗?
答案 0 :(得分:1)
这是一个解决方案:
import re
str_pat = re.compile(r'\((.*)\)')
Cost = {}
for key, value in CostofA.items():
match = str_pat.findall(key)[0]
if match.endswith(','): match = match[:-1]
temp_key = 'Cost(' + match + ')'
if temp_key in Cost:
Cost[temp_key] += value
else:
Cost[temp_key] = value
CostofA = Cost
这将创建一个新的字典Cost
,其中的键基于原始字典CostA中括号括起的数字构建。它使用预编译的正则表达式来匹配这些数字,之后它与endswith(',')
进行核对,如果匹配的模式以,
中的(1,)
结尾 - 如果是,则将其删除。
然后显式地将模式与括号和其他所需的字符串连接,从而创建目标新密钥。如果存在新密钥,则程序会通过旧字典中的值增加其值。如果没有 - 它会创建一个具有该值的新条目。最后,程序会覆盖旧词典。
re.compile是一个已编译的正则表达式对象,如文档中所述:
将正则表达式模式编译为正则表达式对象, 可以使用match()和search()方法进行匹配, 如下所述。
它存储一个给定的固定正则表达式模式用于搜索,并且被认为比每次调用一个新的正则表达式更有效,特别是当程序与同一模式更匹配时,
但使用re.compile()并保存生成的正则表达式 在使用表达式时,重用对象更有效 在一个程序中多次。
这里使用它更加清晰,因为它一次预先定义模式,而不是每次在循环中定义,但如果你的原始字典更大,它实际上可以提供一些性能改进。
答案 1 :(得分:1)
from itertools import groupby data = sorted([(i[0].split(",",1)[1].replace(",)",")"),i[1]) for i in CostofA.items()]) for key, group in groupby(data, lambda x: x[0]): new_dict["Cost"+key] = sum([thing[1] for thing in group])