我有像
这样的词典d = {'user_id':1, 'user':'user1', 'group_id':3, 'group_name':'ordinary users'}
和“映射”字典如:
m = {'user_id':'uid', 'group_id':'gid', 'group_name':'group'}
我想用第二个键中的“替换”第一个字典中的键(例如将'user_id'替换为'uid'等) 我知道密钥是不可变的,我知道如何用'if / else'语句来做。
但也许有办法在一行表达式中做到这一点?
答案 0 :(得分:16)
不确定
d = dict((m.get(k, k), v) for (k, v) in d.items())
答案 1 :(得分:15)
让我们从@karlknechtel那里获取优秀的代码,看看它的作用:
>>> d = dict((m.get(k, k), v) for (k, v) in d.items())
{'gid': 3, 'group': 'ordinary users', 'uid': 1, 'user': 'user1'}
但它是如何运作的?
要构建字典,您可以使用dict()
功能。它需要一个元组列表。在3.x和> 2.7中,您还可以使用字典理解(请参阅@nightcracker的回答)。
让我们剖析一下dict的论点。首先,我们需要m中所有项目的列表。每个项目都是格式(键,值)的元组。
>>> d.items()
[('group_id', 3), ('user_id', 1), ('user', 'user1'), ('group_name', 'ordinary users')]
给定键值k
,我们可以通过m
从m[k]
获得正确的键值。
>>> k = 'user_id'
>>> m[k]
'uid'
不幸的是,并非d
中的所有密钥都存在于m
。
>>> k = 'user'
>>> m[k]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'user'
要解决此问题,您可以使用d.get(x, y)
,如果密钥d[x]
存在则返回x
,如果不存在,则返回默认值y
。现在,如果k
中不存在来自d
的密钥m
,我们只保留它,因此默认值为k
。
>>> m.get(k, k).
'user'
现在我们准备构建一个元组列表以供给dict()
。要在一行中构建列表,我们可以使用list comprehension。
要构建一个正方形列表,您可以这样写:
>>> [x**2 for x in range(5)]
[0, 1, 4, 9, 16]
在我们的案例中,它看起来像这样:
>>> [(m.get(k, k), v) for (k, v) in d.items()]
[('gid', 3), ('uid', 1), ('user', 'user1'), ('group', 'ordinary users')]
那是满口的,让我们再看一遍。
给我一个列表[...]
,其中包含元组:
[(.., ..) ...]
我想为x
中的每个项d
添加一个元组:
[(.., ..) for x in d.items()]
我们知道每个项目都是包含两个组件的元组,因此我们可以将其扩展为两个变量k
和v
。
[(.., ..) for (k, v) in d.items()]
每个元组都应该使用m作为第一个分量的正确密钥,如果m中不存在k则为k,以及来自d的值。
[(m.get(k, k), v) for (k, v) in d.items()]
我们可以将其作为参数传递给dict()
。
>>> dict([(m.get(k, k), v) for (k, v) in d.items()])
{'gid': 3, 'group': 'ordinary users', 'uid': 1, 'user': 'user1'}
看起来不错!但是等等,你可能会说,@ karlknechtel没有使用方括号。
是的,他没有使用列表理解,而是使用generator expression。简单来说,不同之处在于列表推导在内存中构建整个列表,而生成器表达式一次计算项目。如果列表作为中间结果,使用生成器表达式通常是个好主意。在这个例子中,它并没有真正有所作为,但习惯这是一个好习惯。
等效的生成器表达式如下所示:
>>> ((m.get(k, k), v) for (k, v) in d.items())
<generator object <genexpr> at 0x1004b61e0>
如果将生成器表达式作为参数传递给函数,则通常可以省略外部括号。最后,我们得到:
>>> dict((m.get(k, k), v) for (k, v) in d.items())
{'gid': 3, 'group': 'ordinary users', 'uid': 1, 'user': 'user1'}
在一行代码中发生了很多事情。有人说这是不可读的,但是一旦习惯了它,将这些代码延伸到几行似乎是不可读的。只是不要过头了。列表理解和生成器表达式非常强大,但强大的功能带来了巨大的责任。给一个好问题+1!
答案 2 :(得分:6)
在3.x中:
d = {m.get(key, key):value for key, value in d.items()}
它的工作原理是创建一个新字典,其中包含d
中的每个值并映射到新密钥。密钥的检索方式如下:m[key] if m in key else key
,但随后使用默认的.get函数(如果密钥不存在,则支持默认值)。
答案 3 :(得分:1)
为什么要在一行中完成?
result = {}
for k, v in d.iteritems():
result[m.get(k, k)] = v