使用if-else条件理解Python列表

2024-06-01 06:42:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个小的(<;100)名为detected_chems的化学名称列表。在

第二个大得多的(>;1000)iterable;一个字典chem_db,包含化学名称作为键,一个包含化学性质的字典作为值。像这样:

{'chemicalx':{'property1':'smells','property2':'poisonous'},
 'chemicaly':{'property1':'stinks','property2':'toxic'}}

我正在尝试将所有检测到的化学物质与数据库中的进行匹配,并提取它们的属性。在

我研究过这些问题/答案,但似乎不能将其应用于我的案例(抱歉)

所以我创建了一个结果列表res,但是我没有用if x in条件嵌套for循环,而是创建了这个。在

^{pr2}$

这在一定程度上起作用了!在

我在这里做的是创建一个字典列表,其中将包含键:值对化学名称(键)和有关化学物质的信息(作为字典本身,作为值),如果检测到的化学物质在化学数据库(chem_db)中找到。在

问题是并不是所有检测到的化学物质都能在数据库中找到。这可能是因为拼写错误或名称变化(例如,它们包括数字)或类似的原因。在

所以要解决这个问题,我需要确定哪些检测到的化学物质不匹配。我想这可能是个解决办法:

^{3}$

我得到一个语法错误,由于else not_matched.append(det_chem)部分。在

我有两个问题:

1)else条件应该放在哪里以避免语法错误?在

2)是否可以在列表理解中构建not_matched列表,因此我不会先创建空列表。在

res = [{chem:chem_db[chem]}
       for det_chem in detected_chems
       for chem in chem_db.keys()
       if det_chem in chem else print(det_chem)]

我想实现的目标是:

in: len(detected_chems)
out: 20
in: len(res)
out: 18
in: len(not_matched)
out: 2

in: print(not_matched)
out: ['chemical_strange_character$$','chemical___WeirdSPELLING']

这会帮我找到匹配的问题。在


Tags: in名称列表dbif字典notout
3条回答

你应该

if det_chem in chem or not_matched.append(det_chem)

不过,如果你按照评论整理一下,我认为有一种更有效的方法来做你想做的事。上面的解释是append返回None,所以整个if条件的计算结果是False(但该项仍然附加到not_matched列表中)

回复:效率:

^{pr2}$

这应该是一个O(n)操作,字典键上的for循环是一个O(n)操作,而字典恰恰是因为lookup是O(1),所以我们使用基于散列的det_chem in chem_db查找来代替检索和逐个比较它们

额外收获:听写理解(回答问题2)

我不知道为什么要建立一个一键式的字典列表,但可能需要的是一个dict理解,如:

chem_db = {1: 2, 4: 5}
detected_chems = [1, 3]
not_matched = []
res = {det_chem: chem_db[det_chem] for det_chem in detected_chems if
       det_chem in chem_db or not_matched.append(det_chem)}
# output
print(res) # {1: 2}
print(not_matched) # [3]

我想不出用一个list/dict理解来构建not_matched列表,同时也构建{}。在

列表理解的形式上由三个部分组成。让我们用一个例子来说明:

[2 * i          for i in range(10)         if i % 3 == 0]
  1. 第一个部分是一个表达式,它可以是(或在其中使用)三元运算符x if y else z

  2. 第二个部分是一个列表(嵌套的for循环中的多个列表),从中为变量选择值。

  3. 第三个部分(可选)是一个过滤器(用于在第2部分中进行选择),这里不允许使用中的else子句!

因此,如果你想使用else分支,你必须把它放到第一部分

^{pr2}$

语法错误是因为comprehension不接受else子句。在

最终可以使用... if ... else ...三元运算符来确定要放入理解结果中的值。如下所示:

not_matched=[]
res = [{chem:chem_db[chem]} if det_chem in chem else not_matched.append(det_chem)
       for det_chem in detected_chems
       for chem in chem_db.keys()]

但这将是一个坏主意,因为你的None中每一个不匹配的都有None。这是因为... if ... else ...运算符总是返回一个值,在您的例子中,该值将是list.append方法的返回值(=None)。 然后可以过滤res列表以删除None值,但是。。。无聊的。。。在


一个更好的解决方案是简单地保留第一次压缩,并得到原始chem列表和{}列表之间的差异:

^{pr2}$

请注意,我使用了一个已经匹配的chems占位符,而不是真正的代码块,因为存储res的方式根本不实际。实际上,它是一个单键字典的列表,它是一个非sens的列表,字典的作用是保存由键标识的多个值。在

一种解决方法是使用dict理解使res成为字典而不是列表:

res = {chem: chem_db[chem]
       for det_chem in detected_chems
       for chem in chem_db.keys()
       if det_chem in chem}

这样,已经匹配的chems占位符可以替换为res.values()


另外,即使在很多情况下,理解是一个非常酷的特性,但它们并不是一个神奇的特性,应该在所有地方使用。 而且嵌套理解是阅读的真正痛苦,应该避免(至少在我看来)。在

相关问题 更多 >