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