给定一个字典{k1: v1, k2: v2…}我想得到{k1: f(v1), k2: f(v2)…}如果我传递一个函数f。
有这样的内置功能吗?还是我必须
dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])
理想情况下,我只会写
my_dictionary.map_values(f)
or
my_dictionary.mutate_values_with(f)
也就是说,对我来说,原始字典是否发生了突变或创建了一个副本都无关紧要。
虽然我最初的答案没有抓住重点(试图用defaultdict的access key in factory的解决方案来解决这个问题),但我对它进行了重写,提出了当前问题的实际解决方案。
下面就是:
class walkableDict(dict):
def walk(self, callback):
try:
for key in self:
self[key] = callback(self[key])
except TypeError:
return False
return True
用法:
>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)
其思想是对原始字典进行子类化,以赋予其所需的功能:在所有值上“映射”一个函数。
另外一个优点是,这个字典可以用来存储原始数据,就像它是一个字典一样,同时使用回调转换任何请求的数据。
当然,可以随意命名类和函数(在这个答案中选择的名称受到PHP的array_walk()函数的启发)。
注意:try-except块和return语句对于该功能都不是强制的,它们的存在是为了进一步模拟PHP的array_walk行为。
我的方式映射字典
def f(x): return x+2
bill = {"Alice": 20, "Bob": 10}
d = {map(lambda x: f(x),bill.values())}
print('d: ',dict(d))
结果
: d: {22: 12}
在字典的值中映射可迭代对象
bills = {"Alice": [20, 15, 30], "Bob": [10, 35]}
d= {map(lambda v: sum(v),bills.values())}
g= dict(map(lambda v: (v[0],sum(v[1])),bills.items()))
# prints
print('d: ',dict(d))
print('g: ',g)
结果
d: {65: 45}
g: {'Alice': 65, 'Bob': 45}
刚刚遇到这个用例。我实现了gens的答案,添加了一个递归的方法来处理同样是dicts的值:
def mutate_dict_in_place(f, d):
for k, v in d.iteritems():
if isinstance(v, dict):
mutate_dict_in_place(f, v)
else:
d[k] = f(v)
# Exemple handy usage
def utf8_everywhere(d):
mutate_dict_in_place((
lambda value:
value.decode('utf-8')
if isinstance(value, bytes)
else value
),
d
)
my_dict = {'a': b'byte1', 'b': {'c': b'byte2', 'd': b'byte3'}}
utf8_everywhere(my_dict)
print(my_dict)
这在处理Python 2中将字符串编码为字节的json或yaml文件时非常有用