字典的和值与"类似"键Python

时间:2017-10-13 15:50:24

标签: python-2.7 dictionary

我有以下字典:

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.00717.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语句中括号内的数字。有什么建议吗?

2 个答案:

答案 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)

  1. 从词典中生成项目
  2. 通过删除Cost来构建包含元组项的列表推导。 例如,Cost1,(1,2)将是(1,2),而Cost2,(1,2)也将是(1,2)
  3. 对列表进行排序,以便订购所有关键项目
  4. Groupby使用itertools和sum并将其存储在dict中
  5. 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])