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

4

给定以下代码

all_options = { "1": "/test/1", "2": "/test/2", "3": "/test/3" }
selected_options = [ "1", "3" ]

如何从all_options中获取键与selected_options中的条目匹配的条目?

我开始使用List Comprehension,但我卡在了最后一个子句上:

final = ()
[ final.append(option) for option in all_options if ... ]

谢谢你。

1
那是错误的列表推导使用方式。你正在创建一个大的None列表并将其丢弃。只需使用final = [...]即可。 - John La Rooy
5个回答

6
就像这样吗?
>>> 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 comprehension 语法:

{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']

有没有办法让结果成为字典而不是列表? - Misha M
刚想评论这个 :) 这个完美地运行了,谢谢 - Misha M
1
dict版本中不需要列表推导式,只需使用生成器表达式即可。 - agf

1
[option for option in all_options if option in selected_options]

如果有很多选项,您可能希望创建一个selected_optionsset并使用它。


嗯,我认为原帖作者想要的答案是类似于Johnsyweb和我写的那样,但我可能错了。 - NullUserException

1

使用set()替代,利用交集操作

>>> final = set(all_options.keys()) & set(selected_options)
>>> print(final)
{'1', '3'}

上面的代码只返回了键值,但是NullUserException指出可能还需要返回对应的值,可以使用字典推导式:

>>> {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中所需的键。


构建集合仍需要迭代容器 - 但这只需要对每个容器进行一次迭代,而不是有效地迭代笛卡尔积。 - Karl Knechtel
是这样的。我没有那么想过。不过,在我说出来之前,-1就已经出现了。 - Erik Youngren

1
如何从 all_options 中获取与 selected_options 中的条目匹配的键?使用推导式。我们有两种:列表推导式和生成器推导式。
请注意,这取决于您对“条目”的理解。如果您想要一个与之匹配的键/值对的 dict,则需要创建一个推导式来创建键/值对,然后将其提供给 dict 构造函数以创建 dict。
有一条特殊的语法规则,即如果我们仅使用一个参数(例如类构造函数)调用可调用对象,并且该参数是生成器推导式,则我们只需要一对括号(而不是两个:一个用于调用函数,另一个用于标记推导式为推导式)。这使我们可以编写非常自然的代码。
另一方面,如果您只想要一个键的列表,则可以使用列表推导式。(您也可以将生成器推导式传递给 list 构造函数。)
我开始使用列表推导式的方法...

你从根本上对它们的工作原理有误解。你不是用它们重复执行一个动作,而是用它们重复计算结果。你不会在语句的第一部分中进行append调用,因为:(a)列表推导式已经在为你构建序列,所以没有理由创建另一个空序列去附加;(b)append调用在执行附加后返回None,因此最终你会得到一个只包含None值的列表,随后可以抛弃。

列表推导式创建一个值。生成器推导式也创建一个值,但它是一个生成器(因此您必须提取其值才能使用)。

那么,我们该如何编写代码呢?

一个键的list看起来像这样:对于字典中的每个键(在字典上迭代会迭代它的键),我们只想要那个键(没有修改),仅当该键在我们的另一个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 comprehension”,它基本上是一种语法糖,使我们可以编写类似于列表推导式的东西。

谢谢解释,现在更有意义了。 - Misha M

0

我不确定您要返回哪些确切内容,所以我提供了几个选择:

如果您要返回:['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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接