Python列表推导式和'not in'

42
我正在学习Python,并且目前正在学习列表推导式,所以这可能听起来很奇怪。
问题:是否可以使用列表推导式创建一个由在t中但不在s中的元素组成的列表?
我尝试了以下代码,但是它给了我一个错误:
>>> t = [1, 2, 3, 4, 5]
>>> s = [1, 3, 5]
>>>[t for t not in s]

[t for t not in s]
           ^
SyntaxError: invalid syntax

一个推导式只能有两种类型的子句:for spam in eggsif bacon。如果你能够想出如何用 for 循环或 if 检查来编写你想要的内容,那么你就可以了。(在这种情况下,你可以这样做。)如果不能,你需要将代码块分解成函数,或者编写一个显式的循环块语句,而不是一个推导式。 - abarnert
4个回答

71

试试这个:

[x for x in t if x not in s]

您可以在列表推导式中嵌套任何if语句。尝试使用缩进,以获得真正长的条件链,并更清晰地了解代码正在执行的操作。

my_list = [(x,a)
           for x in t
           if x not in s
           if x > 0
           for a in y
           ...]

See?


6
[item  for item  in t if item not in s]

5
这与Lucas的回答完全相同,因此完全是多余的。 - Jonathon Reinhart
6
打字慢是程序员的罪过。 - Leonardo.Z
2
这就是我为什么没有点踩的原因。不幸的是,您经常会发现Stack Overflow是一个追求最先正确答案的竞赛。 - Jonathon Reinhart

2

我知道你在问列表推导式,但是我想指出这个特定的问题最好使用集合set来解决。你需要的结果是集合ts的差集:

>>> t = {1,2,3,4,5}
>>> s = {1,3,5}
>>>
>>> t - s
set([2, 4])
>>>
>>> t.difference(s)
set([2, 4])

希望能够扩展您对Python提供的工具的了解。


3
如果t需要保持顺序并且存在重复元素,则此方法可能无效... 另外,这里只需要一个集合-可能使用较小的集合开始,例如:set(s).symmetric_difference(t) - Jon Clements
2
@JonClements 很有见地。我感谢您的反馈。 - Jonathon Reinhart
实际上,只需要一个是集合即可:“请注意,union()intersection()difference()symmetric_difference()issubset()issuperset()方法的非运算符版本将接受任何可迭代对象作为参数。相比之下,它们基于运算符的对应方法要求参数为集合。” - Jonathon Reinhart

1

为了更好的效率,使用set集合:

mySet = set(s)
result = [x for x in t if x not in mySet]

测试一个集合的成员关系可以在O(1)的时间内完成,但是测试一个列表中的成员关系需要O(n)的时间。


3
这会多次调用 set 函数。 - falsetru
实际上,这个结果会更慢,因为也会创建一个 s 集合。每次检查 s 时,我猜测。 - Lucas Ribeiro
还有另一种方式:list(ifilterfalse(set(s).__contains__, t)) - Jon Clements

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