Python: 双重列表推导式中的if语句

3

我正在尝试编写以下列表推导式:

[writer for writer in writerList if problem in writer.solutions for problem in [1,2,3]]

列表推导式尝试执行以下操作:
  1. 查看writerList中的每个writer
  2. 查看数组[1,2,3]中的每个项
  3. 如果数组[1,2,3]中的所有项也存在于writer.solutions中,则考虑该writer。否则,舍弃该writer。
然而,使用上述列表推导式时,我被告知本地变量problem在赋值前被引用。
我猜我缺乏如何执行这种依赖第二个推导式的if语句的基础理解。我们将不胜感激!

似乎第一个 problem 实例应该是 writer - mhlester
if should be at the end - YOU
[writer for writer in writerList for problem in [1,2,3] if problem in writer.solutions ] - styvane
你使用列表推导式的原因是什么?如果你将它分散到几行中,这个任务会更容易。列表推导式很棒,但它们可能会使复杂的循环难以理解。 - Bryan Oakley
@ssm:如果你需要使用map函数来使用lambda表达式,那么你会失去速度和简洁性;永远不要这样做。你可以很容易地用[w for w in winterList if all(s in (1, 2, 3) for s in w.solutions)]来表达,这实际上更短,并且通常更快。如果你使用了C内置函数并且w.solutions很大,你甚至可以获得(稍微)更高的性能,但是当你需要引用特殊方法时,它看起来很丑陋:[w for w in winterList if all(map((1, 2, 3).__contains__, w.solutions))] - ShadowRanger
显示剩余3条评论
2个回答

2

试试这样做:

[writer for writer in writerList  for problem in [1,2,3] if problem in writer.solutions]

这将创建一个列表,其中包含作者的多个副本(每个解决方案列表中的问题一个副本)。 - Brendan Abel
这个版本在我寻找两个列表之间部分字符串匹配时帮了我大忙,这个问题出人意料的棘手。aList = ['apple', 'banana', 'peach'] bList = ['ap', 'pea'] [b for b in bList for a in aList if b in a] - Evan

0

如果writer.solutionsproblems中的项目是可哈希的(像您示例中提供的整数一样),则可以使用sets来优化和简化此特定问题。可变项,如字典和列表,不可哈希。

problems = set([1, 2, 3])
writers = [writer for writer in writerList if not problems.difference(writer.solutions)]

set.difference(other)会返回集合中不在另一个集合中的项。因此,如果问题集中的所有项都在writer.solutions中,则它将返回一个空集,该集合求值为False(因此是not set.difference())。


非常感谢!这是一个好建议,但是writers.solutions实际上是一个词典。 :/ - brandonio21
问题是什么?你能比较字典键吗?它们是可哈希的。 - Brendan Abel
哦,你绝对是对的。我刚刚尝试使用这种方法,它完美地运行了!哇! - brandonio21
2
.difference 操作会不必要地构造一个缺失项的 set 集合;改用 .issubset 操作(不使用 not 反转结果)可以避免临时变量;我相信将 not problems.difference(writer.solutions) 改为 problems.issubset(writer.solutions) 可以获得相同的结果,并在第一次不匹配时进行短路处理,而无需使用临时变量。 - ShadowRanger
@ShadowRanger 哦,不错!以前没用过。 - Brendan Abel

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