给定以下代码
all_options = { "1": "/test/1", "2": "/test/2", "3": "/test/3" }
selected_options = [ "1", "3" ]
如何从all_options中获取条目,其中键与selected_options的条目匹配?
我开始使用列表理解,但我被困在最后一个子句上:
final = ()
[ final.append(option) for option in all_options if ... ]
感谢
就是这样吗?
>>> dict((option, all_options[option]) for option in selected_options if option in all_options)
{'1': '/test/1', '3': '/test/3'}
从Python 2.7和3开始,您可以使用dict理解语法:
{option : all_options[option] for option in selected_options if option in all_options}
或者,如果你只想要值:
>>> [all_options[option] for option in selected_options if option in all_options]
['/test/1', '/test/3']
[option for option in all_options if option in selected_options]
您可能想将selected_options
制作成set
,如果有很多,则使用它。
如何从键与selected_options中的条目匹配的all_options获取条目?
带着理解。我们有两种:列表理解和生成器理解。
请注意,这取决于您所说的"条目"的含义。如果你想要一个具有匹配的键/值对的dict
,那么你需要一个创建键/值配对的理解,然后通过将其提供给dict
构造函数来创建dict。
有一个特殊的语法规则说,如果我们只用一个参数调用一些可调用的东西(比如类构造函数(,而这个参数是生成器理解,那么我们只需要一对括号(而不是两个:一个用来调用函数,另一个用来将理解标记为理解(。这让我们能够写出看起来非常自然的东西。
另一方面,如果你只想要一个密钥的list
,那么你可以使用列表理解。(您也可以将生成器理解传递给list
构造函数。(
我开始使用列表理解。。。
从根本上讲,你对它们的工作方式有错误的想法。你不会用它们来重复执行一个动作;您可以使用它们来重复计算结果。您不会在语句的第一部分进行append
调用,因为(a(理解已经在为您构建序列,因此没有理由创建另一个空序列来追加;(b( append
调用在进行追加后返回None
,因此您最终会得到一个None值列表,这些值随后会被丢弃。
列表理解会创建一个值。生成器理解也会创建一个值,但它是一个生成器(所以你必须提取它的值才能使用它们(。
那么,我们该如何编写代码呢?
密钥的list
看起来是这样的:对于dict
中的每个密钥(在dict
上迭代(,我们想要该密钥(无需修改(,前提是该密钥在我们的另一个list
中。也就是说,我们想要[key for key in all_options if key in selected_options]
。这正是用Python编写它的方式。一种语言在不含糊的情况下很难再自然地阅读了。
键值对的dict
看起来是这样的:对于dict
的键值对中的每个键值对,我们想要该对,只有当密钥在我们的另一个list
中时。我们想使用这些键值对生成dict
,所以我们将理解封装在dict
构造函数中。为了从dict中获得键值对,我们对其.items()
进行迭代。因此,我们想要一个由键和值构建的dict
,用于原始dict
项中的每个键和值,其中键在另一个list
中。再说一遍,这正是我们所写的:dict((key, value) for (key, value) in all_options if key in selected_options)
。
在最近版本的Python中,我们还可以使用"dict理解",这基本上是语法糖,这样我们就可以写一些看起来更像列表理解的东西。
使用set()
,并利用交叉点操作:
>>> final = set(all_options.keys()) & set(selected_options)
>>> print(final)
{'1', '3'}
上面只返回密钥,但NullUserException指出,问题可能也需要该值,使用dict压缩:
>>> {x: all_options[x] for x in set(all_options.keys()) & set(selected_options)}
{'1': '/test/1', '3': '/test/3'}
为了完整性,这里的只是值:
>>> [all_options[x] for x in set(all_options.keys()) & set(select_options)]
['/test/1', '/test/3']
以下内容是错误的。使用set()
会在两个列表上进行迭代,而不是仅对一个列表进行迭代。
假设选项变大,使用集合会更好。条件列表综合检查其中一个容器中的每一项,但集合交集利用了Python出色的哈希。即使这里的列表理解也只在
all_options
中查找所需的键。
我不确定您要返回的确切内容,所以我给出了几个选择:
如果您试图返回:['1','3']
[option for option in all_options if option in selected_options]
或
如果您试图返回:['/test/1','/test/3']
[all_options[option] for option in all_options if option in selected_options]