检查Python中的列表中是否有(不)

时间:2012-05-02 00:16:19

标签: python list conditional membership

我在Python中有一个元组列表,如果元组不在列表中(如果它在列表中,那么我有一个条件,我想要取分支)想拿if分支)

if curr_x -1 > 0 and (curr_x-1 , curr_y) not in myList: 

    # Do Something

但这并不适合我。我做错了什么?

2 个答案:

答案 0 :(得分:372)

该错误可能在您的代码中的其他位置,因为它应该可以正常工作:

>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True

或者使用元组:

>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True

答案 1 :(得分:7)

  

如何检查Python列表中是否包含某些内容?

最便宜,最易读的解决方案是使用in运算符(或在您的特定情况下为not in)。如文档中所述,

  

运算符innot in测试成员资格。 x in s评估为   如果Truex的成员,则为s,否则为Falsex 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部分的最后一段所述。

  

... innot 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问题:您考虑过set吗?

问自己以下问题:

  • 您是否需要检查一个项目是否在列表中多次?
  • 此检查是在循环内完成还是在重复调用的函数内完成?
  • 您存储在列表中的项目是否可哈希化? IOW,您可以打hash吗?

如果您对这些问题的回答为“是”,则应改用setin上的list成员资格测试的时间复杂度为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__的对象。