302

{ 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)

或者

my_dictionary.mutate_values_with(f)

也就是说,原始字典是否发生变异或创建副本对我来说并不重要。

4

8 回答 8

447

没有这样的功能;最简单的方法是使用字典理解:

my_dictionary = {k: f(v) for k, v in my_dictionary.items()}

在 python 2.7 中,使用.iteritems()方法而不是.items()节省内存。dict 理解语法直到 python 2.7 才引入。

请注意,列表中也没有这种方法;你必须使用列表理解或map()函数。

因此,您也可以使用该map()函数来处理您的 dict:

my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))

但这不是那么可读,真的。

于 2012-09-01T15:33:08.040 回答
36

这些工具非常适合这种简单但重复的逻辑。

http://toolz.readthedocs.org/en/latest/api.html#toolz.dicttoolz.valmap

让你在你想去的地方。

import toolz
def f(x):
  return x+1

toolz.valmap(f, my_list)
于 2014-05-15T20:16:39.583 回答
25

您可以就地执行此操作,而不是创建新的字典,这对于大型字典可能更可取(如果您不需要副本)。

def mutate_dict(f,d):
    for k, v in d.iteritems():
        d[k] = f(v)

my_dictionary = {'a':1, 'b':2}
mutate_dict(lambda x: x+1, my_dictionary)

结果my_dictionary包含:

{'a': 2, 'b': 3}
于 2014-08-24T08:36:20.557 回答
21

由于PEP-0469将 iteritems() 重命名为 items() 和PEP-3113删除了Tuple 参数 unpacking,在 Python 3.x 中,您应该像这样编写Martijn Pieters♦ 答案

my_dictionary = dict(map(lambda item: (item[0], f(item[1])), my_dictionary.items()))
于 2016-09-22T13:36:10.537 回答
4

虽然我的原始答案没有抓住重点(通过尝试使用在 defaultdict 工厂中访问密钥的解决方案来解决这个问题),但我已经对其进行了重新设计,以提出当前问题的实际解决方案。

这里是:

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)

这个想法是对原始 dict 进行子类化以赋予它所需的功能:在所有值上“映射”一个函数。

优点是该字典可用于存储原始数据,就好像它是 a 一样dict,同时根据请求使用回调转换任何数据。

当然,您可以随意命名类和函数(此答案中选择的名称受 PHParray_walk()函数的启发)。

注意:try-except块和return语句都不是该功能所必需的,它们是为了进一步模仿 PHP 的array_walk.

于 2015-05-07T12:22:47.613 回答
2

为了避免从 lambda 内部进行索引,例如:

rval = dict(map(lambda kv : (kv[0], ' '.join(kv[1])), rval.iteritems()))

你也可以这样做:

rval = dict(map(lambda(k,v) : (k, ' '.join(v)), rval.iteritems()))
于 2019-03-29T09:12:30.903 回答
0

刚刚遇到这个用例。我实现了gens's answer,添加了一种递归方法来处理也是 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 文件时很有用

于 2018-04-06T08:40:10.897 回答
0
  • 我映射字典的方式
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}
于 2021-12-20T10:16:42.877 回答