我有一本字典,例如d = {-1: 10, 0: 20, 1: 30, 2: 40}
,其中键k是一些标签,其值对应于计数数。我有一些函数f(x)
,让我们使用f(x)=|x|
,然后我想制作另一个字典d2
,使d2 = {f(x): #counts f(x)}
的所有x
值(原始字典。请注意,f不是单射的,所以f(-1)=f(1)
。是否有一种(Pythonic)的方法可以执行此操作而无需从头开始显式循环和构造d2
?
在此示例中,所需的字典为d2 = {1: 40, 0:20, 2:40}
编辑:我当前的解决方案
def map_dictionary(d, f):
d2 = {}
for k in d:
if f(k) in d2:
d2[f(k)] += d[k]
else:
d2[f(k)] = d[k]
return d2
答案 0 :(得分:2)
一个想法是使用defaultdict
:
from collections import defaultdict
d = {-1: 10, 0: 20, 1: 30, 2: 40}
f = abs
d2 = defaultdict(int)
for k, v in d.items():
d2[f(k)] += v
print(d2) # defaultdict(<class 'int'>, {1: 40, 0: 20, 2: 40})
defaultdict(int)
将为尚不存在的任何密钥返回0
(int()
返回的结果)。
更新问题后更新。不,没有循环就无法做到这一点(您绝对必须来查看键)-但是有一种方式可以做到而无需创建新字典(对于特殊情况{{ 1}};此方法是否有效取决于您的f = abs
:
f
请注意,在第一个循环中python禁止d = {-1: 10, 0: 20, 1: 30, 2: 40}
neg_keys = []
for k, v in d.items():
if k < 0:
neg_keys.append(k)
d[-k] = d.get(-k, 0) + v
for k in neg_keys:
del d[k]
print(d) # {0: 20, 1: 40, 2: 40}
(出于充分的理由!del
)。
答案 1 :(得分:1)
collections.Counter
可以执行此操作而无需添加任何内容:
from collections import Counter
d = {-1: 10, 0: 20, 1: 30, 2: 40}
d2 = Counter([abs(x) for x, y in d.items() for i in range(y)])
print(d2) # Counter({1: 40, 2: 40, 0: 20})
答案 2 :(得分:0)
您可以考虑使用dict comprehension。
def f(x):
return abs(x)
d = {-1: 10, 0: 20, 1: 30, 2: 40}
d2 = {
f(key): d[f(key)] + d[key] if
f(key) != key and f(key) in d.keys()
else d[key]
for key in sorted( d.keys(), reverse=True )
}
print(d2)
#{2: 40, 1: 40, 0: 20}