我在Python中有一个元组列表,并且有一个条件,如果元组不在列表中,那么我只想采用该分支(如果它在列表中,那么我就不想采用if分支)

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

    # Do Something


但这对我来说不是真的。我做错了什么?

评论

请注意,3 -1> 0和(4-1,5)不在[]⤇True中,因此错误不是运算符优先级之一。

“不是真的为我工作”是什么意思?您期望发生什么?实际发生了什么?哪些确切的列表内容会引发问题?

为什么不尝试myList.count((curr_x,curr_y)),如果(curr_x,curr_y)不在myList中,则结果将为0

您是否考虑过使用集合?

打败我,这是我八年前在大学时写的。如果您愿意,可以提供一个最小的可复制示例:)

#1 楼

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

>>> 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


评论


@Zack:如果您不知道这一点,可以在COLLECTION中没有ELEMENT的情况下进行:

– ninjagecko
2012年5月2日,0:23



@ninjagecko:取决于效率可能较低甚至不正确的容器类型。参见例如布隆过滤器。

–orlp
2012年5月2日,0:24

@nightcracker这没有意义,因为B中的A减少为不包含B .__ contains __(A),这与B中的A不减少为B .__ contains __(A)相同。

– Dan D.
2012年5月2日,0:33

哇,我可以宣誓Python拥有__notcontains__之类的东西。对不起,那我所说的只是胡说。

–orlp
2012年5月2日,0:35



@ std''OrgnlDave唯一可能发生的方法是,如果没有比没有的优先级更高的优先级。考虑ast.dump(ast.parse(“ not A B”)。body [0])的结果,该结果为“ Expr(value = UnaryOp(op = Not(),操作数= Compare(left = Name(id)) ='A',ctx = Load()),ops = [In()],比较器= [名称(id ='B',ctx = Load())]))))))“如果未与A紧密分组会期望结果为“ Expr(值=比较(左= UnaryOp(op = Not(),操作数=名称(id ='A',ctx = Load()))),ops = [In()],比较器= [Name(id ='B',ctx = Load())])))“,是“(B中的非A)”的解析。

– Dan D.
16 Dec 2'在10:57

#2 楼


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


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


运算符innot in测试成员资格。如果x in sTrue的成员,则x求值为
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将在内部调用它,如文档“比较”部分的最后一段所述。


... 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吗?

如果您对这些问题的回答是“是”,则应该改用set。在in上进行的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__的对象。

评论


集并不总是一个选项(例如,当具有可变项列表时)。对于大型集合:无论如何,为查询建立集合的时间为O(n),并且可能使内存使用量增加一倍。如果您还没有进行查找,那么它并不是制作/维护一个的最佳选择。

– Wim
19年2月1日在20:41