파이썬의 목록에없는 것이 있는지 확인하십시오.


314

파이썬 에 튜플 목록이 있고 튜플이 목록에없는 경우에만 지점을 가져 가고 싶은 조건부가 있습니다 (목록에있는 경우 if 분기를 사용하고 싶지 않습니다)

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

    # Do Something

이것은 실제로 나를 위해 작동하지 않습니다. 내가 뭘 잘못 했니?


1
참고는 3 -1 > 0 and (4-1 , 5) not in []True따라서 오류 운영자 우선 아니다.
Dan D.

6
"정말 나를 위해 일하지 않는다"는 것은 무엇을 의미합니까? 당신은 어떻게 될 것으로 예상합니까? 실제로 어떻게됩니까? 어떤 정확한 목록 내용이 문제를 유발합니까?
Karl Knechtel 1

왜 시도하지 myList.count((curr_x, curr_y))경우 (curr_x, curr_y)에없는 myList결과가 될 것입니다0
LittleLittleQ


2
이 "내 코드가 실제로 작동하지 않습니다"라는 질문에 297 번의 공감대가 어떻게 나타 났습니까? 최소한의 재현 가능한 예를 제시하십시오 .
gerrit

답변:


502

버그는 아마도 코드의 다른 곳에있을 것입니다.

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

11
@Zack : 당신이 이것에 대해 몰랐다면, 당신은 그냥 할 수 있습니다if not ELEMENT in COLLECTION:
ninjagecko

@ninjagecko : 덜 효율적이거나 부정확 할 수있는 컨테이너 유형에 따라 다릅니다. 블룸 필터를 참조하십시오 .
orlp

14
@nightcracker 즉, 어떠한 의미하지 않습니다 A not in B일에 감소 not B.__contains__(A)하는 것은 무엇과 동일 not A in B하다로 감소된다 not B.__contains__(A).
Dan D.

1
와우, 나는 파이썬이 같은 것을 맹세 할 수 있었다 __notcontains__. 미안하지만 내가 한 말은 헛소리 야
orlp

2
@ std''OrgnlDave 발생할 수있는 유일한 방법은 그렇지 않은 not것보다 우선 순위가 높은 경우 in입니다. 의 결과 고려 ast.dump(ast.parse("not A in B").body[0])의 결과를하는 "Expr(value=UnaryOp(op=Not(), operand=Compare(left=Name(id='A', ctx=Load()), ops=[In()], comparators=[Name(id='B', ctx=Load())])))"경우는 notA를 단단히 그룹화를 한 것으로 결과를 예상 한 것 "Expr(value=Compare(left=UnaryOp(op=Not(), operand=Name(id='A', ctx=Load())), ops=[In()], comparators=[Name(id='B', ctx=Load())]))"에 대한 해석이다 "(not A) in B".
Dan D.

20

파이썬의 목록에 무언가가 없는지 어떻게 확인합니까?

가장 저렴하고 읽기 쉬운 솔루션은 in연산자 (또는 특정 경우 not in)를 사용하는 것입니다. 설명서에서 언급했듯이

운영자 innot 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마지막 단락에 언급 된대로 내부적 으로 메소드를 호출합니다 .

... 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항목의 색인을 검색하는 데 사용할 수 있습니다. 해당 요소가 없으면 a ValueError가 발생합니다.
  • list.count 발생 횟수를 계산하려는 경우 사용할 수 있습니다.

XY 문제 : 당신은 sets 를 고려 했습니까 ?

다음과 같은 질문을 해보십시오.

  • 항목이 목록에 두 번 이상 있는지 확인해야합니까?
  • 이 검사는 루프 또는 반복적으로 호출되는 함수 내에서 수행됩니까?
  • 목록에 저장 한 항목이 해시 가능합니까? IOW, 당신 hash은 그들 에게 전화 할 수 있습니까?

이 질문에 "예"라고 대답 한 경우 set대신 사용하십시오 . 의 in멤버쉽 테스트 list는 O (n) 시간 복잡성입니다. 이것은 파이썬이 목록의 선형 스캔을 수행하여 각 요소를 방문하고 검색 항목과 비교해야한다는 것을 의미합니다. 이 작업을 반복적으로 수행하거나 목록이 크면이 작업에 오버 헤드가 발생합니다.

set반면에 객체는 일정한 시간 멤버쉽 확인을 위해 값을 해시합니다. 확인은 다음을 사용하여 수행됩니다 in.

1 in {1, 2, 3} 
# True

'a' not in {'a', 'b', 'c'}
# False

(1, 2) in {('a', 'c'), (1, 2)}
# True

불행히도 검색 / 검색하지 않는 요소가 목록의 끝에있을 때 파이썬은 목록을 끝까지 스캔합니다. 이것은 아래의 타이밍에서 분명합니다.

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


2
세트는 항상 옵션이 아닙니다 (예 : 변경 가능한 항목 목록이있는 경우). 대규모 콜렉션의 경우 : 조회 세트를 작성하는 것은 어쨌든 O (n) 시간이며 메모리 사용량을 두 배로 늘릴 수 있습니다. 아직 검색하지 않은 경우 항상 검색 / 유지 관리하는 것이 최선의 선택은 아닙니다.
wim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.