Python:检查是否有任何列表元素是字典中的键



给定以下代码

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]

最新更新