다음 항목 중 하나가 목록에 있는지 확인하는 방법은 무엇입니까?


220

다음 항목 중 하나라도 목록에 있는지 확인할 수있는 간단한 방법을 찾으려고하지만 첫 번째 시도가 작동하지 않습니다. 이를 수행하는 함수를 작성하는 것 외에도 여러 항목 중 하나가 목록에 있는지 확인하는 짧은 방법입니다.

>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True

재밌는 일, 나는 '그리고'행동 방식을 확인했습니다. a = [1, 2] b = [3, 5, 2, 6, 8, 9] c = [3, 5, 6, 8, 1, 9] print( (1 and 2) in b ,(2 and 1) in b ,(1 and 2) in c ,(2 and 1) in c, sep='\n')True False입니다 False True
Piotr Kamoda 2016 년

답변:


266
>>> L1 = [2,3,4]
>>> L2 = [1,2]
>>> [i for i in L1 if i in L2]
[2]


>>> S1 = set(L1)
>>> S2 = set(L2)
>>> S1.intersection(S2)
set([2])

빈 목록과 빈 세트는 모두 False이므로 값을 직접 진리 값으로 사용할 수 있습니다.


6
교차 아이디어는이 아이디어를 주었다. return len (set (a) .intersection (set (b)))
Deon

13
FWIW-속도 비교를했는데 여기에 제공된 첫 번째 솔루션은 금식이었습니다.
jackiekazil 2016 년

2
생성기를 사용하는 @ user89788의 답변 anyTrue값을 찾 자마자 일찍 돌아올 수 있기 때문에 훨씬 더 빠릅니다 . 전체 목록을 먼저 작성할 필요가 없습니다.
Anentropic

목록에 중복 항목이 있으면 두 번째 / 세트 솔루션이 작동하지 않습니다 (세트에 각 항목 중 하나만 포함됨). `L1 = [1,1,2,3] '및'L2 = [1,2,3] '이면 모든 항목이 교차하는 것으로 보입니다.
donrondadon

나는 이것이 거의 10 살이라는 것을 알고 있지만 첫 번째 해결책은 나에게 효과가없는 것 같습니다. 문자열에 대해 L2의 숫자를 대체했으며 다음과 같은 오류가 발생합니다. TypeError : 'in <string>'문자열이 목록이 아닌 왼쪽 피연산자로 문자열이 필요함
roastbeeef

227

아, 토비아스 당신이 날 이겼어요. 귀하의 솔루션 에서이 약간의 변형을 생각하고있었습니다.

>>> a = [1,2,3,4]
>>> b = [2,7]
>>> print(any(x in a for x in b))
True

5
나는 이것이 매우 오래된 대답이라는 것을 알고 있지만 하나의 목록이 매우 길고 다른 목록이 짧은 경우 더 빠른 성능을내는 순서가 있습니까? (즉, x in long for x in shortvs x in short for x in long)
Luke Sapan 님이

11
@LukeSapan : 맞습니다. 이 순서는 "print any (x (min (a, b, key = len) in x for min (a, b, key = len))")를 통해 얻을 수 있습니다. x는 짧게 x를 길게 사용합니다.
Nuclearman

2
이것은 발전기를 사용하기 때문에 가장 좋은 대답이며 일치하는 것이 발견되는 즉시 반환됩니다 (다른 사람이 말한 것처럼이 답변은 아닙니다!).
dotcomly

4
@Nuclearman, 조심 : 두 목록 ab길이가 같은 경우 max와 min은 가장 왼쪽 목록을 반환하여 any()통화가 양쪽에서 동일한 목록으로 작동합니다. 길이를 반드시 확인해야하는 경우 두 번째 호출에서 목록 순서를 반대로하십시오 any(x in max(a, b, key=len) for x in (b, a, key=len)).
노아 보가트

3
@NoahBogart 당신은 정확하고 그 해결책은 어느 것만큼이나 좋아 보입니다. 나는 또한 당신이 의미하는 것으로 추정합니다 : any(x in max(a, b, key=len) for x in min(b, a, key=len))(분을 놓쳤습니다).
Nuclearman

29

아마도 좀 더 게으르다.

a = [1,2,3,4]
b = [2,7]

print any((True for x in a if x in b))

1
내가 게시 한 것과 거의 동일합니다.
Bastien Léonard

5
@ BastienLéonard ... 제너레이터를 사용하여 any일찍 반환 할 수 있기 때문에 훨씬 빠릅니다. 버전은 any사용 하기 전에 전체 목록을 이해해야 합니다. @ user89788의 답변은 이중 괄호가 불필요하기 때문에 약간 더 좋습니다
Anentropic

17

코드가 실제로 말하는 것을 생각하십시오!

>>> (1 or 2)
1
>>> (2 or 1)
2

아마 그것을 설명해야합니다. :) 파이썬은 분명히 "게으른 것"을 구현합니다. 다음과 같이 수행합니다.

def or(x, y):
    if x: return x
    if y: return y
    return False

첫 번째 예 x == 1y == 2. 두 번째 예에서는 그 반대입니다. 따라서 순서에 따라 다른 값을 반환합니다.


16
a = {2,3,4}
if {1,2} & a:
    pass

코드 골프 버전. 적절하다면 세트 사용을 고려하십시오. 나는 이것이 목록 이해력보다 더 읽기 쉽다는 것을 안다.


12

목록 이해없이 한 줄.

>>> any(map(lambda each: each in [2,3,4], [1,2]))
True
>>> any(map(lambda each: each in [2,3,4], [1,5]))
False
>>> any(map(lambda each: each in [2,3,4], [2,4]))
True


6

파이썬 3에서는 압축 풀기 별표를 사용할 수 있습니다. 두 가지 목록이 제공됩니다.

bool(len({*a} & {*b}))

편집 : 알칸 엔의 제안을 통합


1
@Anthony는 a에 요소를 포함하는 세트를 만들고 b에 요소를 포함하는 다른 세트를 작성한 다음 해당 세트 사이의 교차점 (공유 요소)을 찾고 any ()는 진실한 요소가 있으면 true를 리턴합니다. 유일한 공유 요소가 잘못된 경우 (예 : 숫자 0) 솔루션이 작동하지 않습니다. len ()을 any ()보다 사용하는 것이 좋습니다.
alkanen

1
@alkanen Good call
Daniel Braun

왜 설정 기능을 사용하지 않습니까?
Alex78191

5

"a가 b인지 확인하십시오"라고 생각하면 해시 (이 경우 설정)를 생각하십시오. 가장 빠른 방법은 확인하려는 목록을 해시 한 다음 각 항목을 확인하는 것입니다.

이것이 Joe Koberg의 답변이 빠른 이유입니다. 설정된 교차점 확인이 매우 빠릅니다.

데이터가 많지 않은 경우 세트를 만드는 것은 시간 낭비 일 수 있습니다. 따라서 목록 세트를 만들고 각 항목을 확인할 수 있습니다.

tocheck = [1,2] # items to check
a = [2,3,4] # the list

a = set(a) # convert to set (O(len(a)))
print [i for i in tocheck if i in a] # check items (O(len(tocheck)))

확인하려는 항목 수가 적 으면 차이를 무시할 수 있습니다. 그러나 큰 목록에서 많은 숫자를 확인하십시오 ...

테스트 :

from timeit import timeit

methods = ['''tocheck = [1,2] # items to check
a = [2,3,4] # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',

'''L1 = [2,3,4]
L2 = [1,2]
[i for i in L1 if i in L2]''',

'''S1 = set([2,3,4])
S2 = set([1,2])
S1.intersection(S2)''',

'''a = [1,2]
b = [2,3,4]
any(x in a for x in b)''']

for method in methods:
    print timeit(method, number=10000)

print

methods = ['''tocheck = range(200,300) # items to check
a = range(2, 10000) # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',

'''L1 = range(2, 10000)
L2 = range(200,300)
[i for i in L1 if i in L2]''',

'''S1 = set(range(2, 10000))
S2 = set(range(200,300))
S1.intersection(S2)''',

'''a = range(200,300)
b = range(2, 10000)
any(x in a for x in b)''']

for method in methods:
    print timeit(method, number=1000)

속도 :

M1: 0.0170331001282 # make one set
M2: 0.0164539813995 # list comprehension
M3: 0.0286040306091 # set intersection
M4: 0.0305438041687 # any

M1: 0.49850320816 # make one set
M2: 25.2735087872 # list comprehension
M3: 0.466138124466 # set intersection
M4: 0.668627977371 # any

지속적으로 빠른 방법은 (목록의) 하나의 세트를 만드는 것입니다.


3

경우에 따라 (예 : 고유 목록 요소) 설정 작업을 사용할 수 있습니다.

>>> a=[2,3,4]
>>> set(a) - set([2,3]) != set(a)
True
>>> 

또는 사용 ) (set.isdisjoint를 ,

>>> not set(a).isdisjoint(set([2,3]))
True
>>> not set(a).isdisjoint(set([5,6]))
False
>>> 

2

이것은 한 줄로 할 것입니다.

>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True

여기에 True가 표시되지 않습니다 >>> print a [2, 3, 4] >>> print b [2, 7] >>> reduce (lambda x, y : x in b, a) False
Deon

네. 네가 옳아. reduce ()는 내가 생각했던 방식으로 부울 값을 처리하지 않았습니다. 위에서 쓴 개정판은 그 경우에 효과적입니다.
Chris Upchurch

2

다른 답변과 의견에 언급 된 여러 솔루션을 수집 한 다음 속도 테스트를 실행했습니다. not set(a).isdisjoint(b)가장 빠르다는 결과가 나왔을 때 속도가 느려지지 않았습니다 False.

세 개의 실행 각각의 가능한 구성의 작은 샘플 테스트 ab. 시간은 마이크로 초입니다.

Any with generator and max
        2.093 1.997 7.879
Any with generator
        0.907 0.692 2.337
Any with list
        1.294 1.452 2.137
True in list
        1.219 1.348 2.148
Set with &
        1.364 1.749 1.412
Set intersection explcit set(b)
        1.424 1.787 1.517
Set intersection implicit set(b)
        0.964 1.298 0.976
Set isdisjoint explicit set(b)
        1.062 1.094 1.241
Set isdisjoint implicit set(b)
        0.622 0.621 0.753

import timeit

def printtimes(t):
    print '{:.3f}'.format(t/10.0),

setup1 = 'a = range(10); b = range(9,15)'
setup2 = 'a = range(10); b = range(10)'
setup3 = 'a = range(10); b = range(10,20)'

print 'Any with generator and max\n\t',
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup3).timeit(10000000))
print

print 'Any with generator\n\t',
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup3).timeit(10000000))
print

print 'Any with list\n\t',
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup3).timeit(10000000))
print

print 'True in list\n\t',
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup3).timeit(10000000))
print

print 'Set with &\n\t',
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup3).timeit(10000000))
print

print 'Set intersection explcit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup3).timeit(10000000))
print

print 'Set intersection implicit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup3).timeit(10000000))
print

print 'Set isdisjoint explicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup3).timeit(10000000))
print

print 'Set isdisjoint implicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup3).timeit(10000000))
print

0

나는 나의 상황이 당신이 찾고있는 것이 아닐 수도 있지만, 그것은 당신의 생각에 대안을 제공 할 수 있다고 말해야합니다.

set () 및 any () 메서드를 모두 시도했지만 여전히 속도에 문제가 있습니다. 그래서 Raymond Hettinger는 파이썬의 모든 것이 사전이며 가능할 때마다 dict를 사용한다고 말했습니다. 그것이 제가 시도한 것입니다.

나는 int와 함께 defaultdict를 사용하여 부정적인 결과를 표시하고 첫 번째 목록의 항목을 두 번째 목록의 키로 사용했습니다 (defaultdict로 변환). dict로 즉시 조회 할 수 있기 때문에 해당 항목이 defaultdict에 있는지 즉시 알 수 있습니다. 두 번째 목록의 데이터 구조를 항상 변경할 수는 없지만 처음부터 할 수 있다면 훨씬 빠릅니다. list2 (큰 목록)를 defaultdict로 변환해야 할 수 있습니다. 여기서 key는 작은 목록에서 확인하려는 잠재적 값이며 값은 1 (적중) 또는 0 (적중 없음, 기본값)입니다.

from collections import defaultdict
already_indexed = defaultdict(int)

def check_exist(small_list, default_list):
    for item in small_list:
        if default_list[item] == 1:
            return True
    return False

if check_exist(small_list, already_indexed):
    continue
else:
    for x in small_list:
        already_indexed[x] = 1

-4

단순한.

_new_list = []
for item in a:
    if item in b:
        _new_list.append(item)
    else:
        pass

1
이것은 질문에 대답하지 않습니다. OP는 list의 값이 list 에 있는지 알고 싶어 a합니다 b.
That1Guy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.