如何在 Python 的列表中检查某些内容是否(不在)?
最便宜和最易读的解决方案是使用in 运算符(或在您的特定情况下,not in)。如文档中所述,
运算符in 和not in 测试成员资格。 x in s 评估为
True 如果x 是s 的成员,则False 否则。 x not in s 返回
x in s的否定。
另外,
运算符not in 被定义为具有in 的逆真值。
y not in x 在逻辑上与not y in x 相同。
这里有几个例子:
'a' in [1, 2, 3]
# False
'c' in ['a', 'b', 'c']
# True
'a' not in [1, 2, 3]
# True
'c' not in ['a', 'b', 'c']
# False
这也适用于元组,因为元组是可散列的(因为它们也是不可变的):
(1, 2) in [(3, 4), (1, 2)]
# True
如果 RHS 上的对象定义了 __contains__() 方法,in 将在内部调用它,如文档的 Comparisons 部分的最后一段所述。
...in 和 not in,
由可迭代或实现的类型支持
__contains__() 方法。例如,您可以(但不应该)这样做:
[3, 2, 1].__contains__(1)
# True
in 短路,因此如果您的元素位于列表的开头,in 的计算速度会更快:
lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst # Expected to take longer time.
68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
如果您想做的不仅仅是检查某个项目是否在列表中,还有以下选择:
-
list.index 可用于检索项目的索引。如果该元素不存在,则会引发 ValueError。
-
如果要统计出现次数,可以使用
list.count。
XY 问题:你考虑过sets 吗?
问自己这些问题:
- 您是否需要多次检查某个项目是否在列表中?
- 此检查是在循环内完成的,还是在重复调用的函数内完成的?
- 您存储在列表中的项目是否可散列? IOW,你可以给他们打电话
hash 吗?
如果您对这些问题的回答为“是”,则应改用set。在lists 上的in 成员资格测试是 O(n) 时间复杂度。这意味着 python 必须对列表进行线性扫描,访问每个元素并将其与搜索项进行比较。如果您重复执行此操作,或者列表很大,则此操作将产生开销。
set 对象,另一方面,散列它们的值以进行恒定时间成员资格检查。检查也是使用in:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
如果您很不幸,您正在搜索/未搜索的元素位于列表的末尾,python 将一直扫描到列表的末尾。从以下时间可以看出这一点:
l = list(range(100001))
s = set(l)
%timeit 100000 in l
%timeit 100000 in s
2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
提醒一下,只要您存储和查找的元素是可散列的,这是一个合适的选项。 IOW,它们要么必须是不可变类型,要么必须是实现 __hash__ 的对象。