我正在尝试添加相同键的字典值。在下面的示例中,我在尝试添加“相同”键的值时删除了每个键的版本编号。
item_dict = {
"item_C_v001" : 100,
"item_C_v002" : 100,
"item_A_v001" : 50,
"item_B_v001" : 75
}
我的预期输出应为:
"item_C_v" : 200,
"item_A_v" : 50,
"item_B_v" : 75
但是如果我尝试打印item_dict
,我会得到以下内容:
"item_C_v" : 100,
"item_A_v" : 50,
"item_B_v" : 75
但是在我试图剥离的那一刻,似乎item_C_v
被读了一次。如何让它“两次”读取,以便我可以将200
作为它的输出?
答案 0 :(得分:2)
您可以使用collections.defaultdict(int)
对结果进行分组,并将结果与您可以获得的键的所需部分相加,例如正则表达式。这些方面的东西:
In [1]: from collections import defaultdict
In [2]: import re
In [3]: item_dict = {
...: "item_C_v001" : 100,
...: "item_C_v002" : 100,
...: "item_A_v001" : 50,
...: "item_B_v001" : 75
...: }
In [4]: result = defaultdict(int)
In [5]: for key, value in item_dict.items():
...: result[re.search(r"(\w+?)\d+", key).group(1)] += value
In [6]: dict(result)
Out[6]: {'item_A_v': 50, 'item_B_v': 75, 'item_C_v': 200}
您可以使用str.partition()
:
>>> key = "item_C_v001"
>>> "".join(key.partition("_v")[:-1])
'item_C_v'
或者,简单地通过切片,如果数字之前的子串的长度或字符串末尾的位数是常数:
>>> key = "item_C_v001"
>>> key[:8]
'item_C_v'
>>> key[:-3]
'item_C_v'
或者,通过右键剥离数字:
>>> import string
>>> key.rstrip(string.digits)
'item_C_v'
答案 1 :(得分:2)
您可以迭代原始字典并将新密钥附加到新字典中,如果密钥已存在,则将当前值添加到原始值。
item_dict = {
"item_C_v001" : 100,
"item_C_v002" : 100,
"item_A_v001" : 50,
"item_B_v001" : 75
}
new_dict = {}
for k, v in item_dict.items():
k_new = k[:-3]
new_dict[k_new] = new_dict[k_new] + v if k_new in new_dict.keys() else v
print (new_dict)
>>> {'item_A_v': 50, 'item_C_v': 200, 'item_B_v': 75}
答案 2 :(得分:2)
您可以使用itertools.groupby()
收集所有类似的密钥,然后构建一个新的字典,汇总所有组值,例如:
>>> import itertools as it
>>> {gk: sum(item_dict[k] for k in g) for gk, g in it.groupby(item_dict, lambda k: k[:-3])}
{'item_A_v': 50, 'item_B_v': 75, 'item_C_v': 200}
@alecxe描述了获取密钥所需部分的几种方法,上面使用key[-3]
。
请求获取count
和sum
,您可以在一个简单的循环中实现并管理计数器,但这是一种方法:
>>> from collections import deque
>>> {key: deque(enumerate(it.accumulate(item_dict[k] for k in g), 1), maxlen=1).pop()
... for key, g in it.groupby(item_dict, lambda key: key[:-3])}
{'item_A_v': (1, 50), 'item_B_v': (1, 75), 'item_C_v': (2, 200)}