[python] 한 목록에서 발생하는 모든 요소를 다른 목록에서 제거
하자 내가 두 개의 목록이 말을 l1
하고 l2
. in의 l1 - l2
모든 요소를 반환하는 을 수행하고 싶습니다 .l1
l2
이 작업을 수행하는 순진한 루프 접근 방식을 생각할 수 있지만 실제로는 비효율적입니다. 이것을하는 pythonic하고 효과적인 방법은 무엇입니까?
예를 들어, 내가 가지고있는 경우 l1 = [1,2,6,8] and l2 = [2,3,5,8]
, l1 - l2
반환해야[1,6]
답변
파이썬에는 List Comprehensions 라는 언어 기능 이있어 이러한 종류의 작업을 매우 쉽게 수행 할 수 있습니다. 다음 문장은 원하는 것을 정확하게 수행하고 결과를 저장합니다 l3
.
l3 = [x for x in l1 if x not in l2]
l3
포함합니다 [1, 6]
.
답변
한 가지 방법은 세트를 사용하는 것입니다.
>>> set([1,2,6,8]) - set([2,3,5,8])
set([1, 6])
답변
대안으로 원하는 결과를 얻기 위해 람다 식과 함께 사용할filter
수도 있습니다. 예를 들면 다음과 같습니다.
>>> l1 = [1,2,6,8]
>>> l2 = set([2,3,5,8])
# v `filter` returns the a iterator object. Here I'm type-casting
# v it to `list` in order to display the resultant value
>>> list(filter(lambda x: x not in l2, l1))
[1, 6]
성능 비교
여기에 언급 된 모든 답변의 성능을 비교하고 있습니다. 예상대로 Arkku의 set
기본 작업은 가장 빠릅니다.
-
Arkku의 Set Difference -First (루프 당 0.124 usec)
mquadri$ python -m timeit -s "l1 = set([1,2,6,8]); l2 = set([2,3,5,8]);" "l1 - l2" 10000000 loops, best of 3: 0.124 usec per loop
-
set
조회를 통한 Daniel Pryden의 목록 이해 -초 (루프 당 0.302 usec)mquadri$ python -m timeit -s "l1 = [1,2,6,8]; l2 = set([2,3,5,8]);" "[x for x in l1 if x not in l2]" 1000000 loops, best of 3: 0.302 usec per loop
-
일반 목록에 대한 도넛의 목록 이해 -세 번째 (루프 당 0.552 usec)
mquadri$ python -m timeit -s "l1 = [1,2,6,8]; l2 = [2,3,5,8];" "[x for x in l1 if x not in l2]" 1000000 loops, best of 3: 0.552 usec per loop
-
Moinuddin Quadri를 사용하여
filter
-네 번째 (루프 당 0.972 usec)mquadri$ python -m timeit -s "l1 = [1,2,6,8]; l2 = set([2,3,5,8]);" "filter(lambda x: x not in l2, l1)" 1000000 loops, best of 3: 0.972 usec per loop
-
의하기 Akshay Hazari의 사용 조합
reduce
+filter
– 다섯 번째 (루프 당 3.97 마이크로 초)mquadri$ python -m timeit "l1 = [1,2,6,8]; l2 = [2,3,5,8];" "reduce(lambda x,y : filter(lambda z: z!=y,x) ,l1,l2)" 100000 loops, best of 3: 3.97 usec per loop
추신 : set
순서를 유지하지 않고 목록에서 중복 요소를 제거합니다. 따라서 필요한 경우 설정된 차이를 사용하지 마십시오 .
답변
여기에서 Donut의 답변과 다른 답변을 확장하면 목록 이해 대신 생성기 이해를 사용하고 set
데이터 구조 를 사용하여 더 나은 결과를 얻을 수 있습니다 ( in
연산자는 목록에서 O (n)이지만 O (1) 이므로 세트에).
다음은 귀하에게 적합한 기능입니다.
def filter_list(full_list, excludes):
s = set(excludes)
return (x for x in full_list if x not in s)
결과는 필터링 된 목록을 느리게 가져 오는 반복 가능합니다. 실제 목록 객체가 필요한 경우 (예 : len()
결과에 대해 수행해야하는 경우 ) 다음과 같이 목록을 쉽게 작성할 수 있습니다.
filtered_list = list(filter_list(full_list, excludes))
답변
Python 세트 유형을 사용하십시오. 그것은 가장 파이썬적인 것입니다. 🙂
또한 네이티브이기 때문에 가장 최적화 된 방법이어야합니다.
보다:
http://docs.python.org/library/stdtypes.html#set
http://docs.python.org/library/sets.htm (이전 파이썬의 경우)
# Using Python 2.7 set literal format.
# Otherwise, use: l1 = set([1,2,6,8])
#
l1 = {1,2,6,8}
l2 = {2,3,5,8}
l3 = l1 - l2
답변
사용 설정 함축 {x의 X의 L2} 또는 세트 (L2)의 세트를 얻기 위해, 다음 사용 목록 함축을 목록을 얻으려면
l2set = set(l2)
l3 = [x for x in l1 if x not in l2set]
벤치 마크 테스트 코드 :
import time
l1 = list(range(1000*10 * 3))
l2 = list(range(1000*10 * 2))
l2set = {x for x in l2}
tic = time.time()
l3 = [x for x in l1 if x not in l2set]
toc = time.time()
diffset = toc-tic
print(diffset)
tic = time.time()
l3 = [x for x in l1 if x not in l2]
toc = time.time()
difflist = toc-tic
print(difflist)
print("speedup %fx"%(difflist/diffset))
벤치 마크 테스트 결과 :
0.0015058517456054688
3.968189239501953
speedup 2635.179227x
답변
대체 솔루션 :
reduce(lambda x,y : filter(lambda z: z!=y,x) ,[2,3,5,8],[1,2,6,8])