[python] 파이썬은 다른 목록에없는 하나의 목록에서 요소를 찾습니다 [중복]

한 목록에는 있지만 다른 목록에는없는 특정 요소의 새 목록을 만들려면 두 목록을 비교해야합니다. 예를 들면 :

main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"] 

list_1을 반복하고 list_1에없는 list_2의 모든 요소를 ​​main_list에 추가하고 싶습니다.

결과는 다음과 같아야합니다.

main_list=["f", "m"]

파이썬으로 어떻게 할 수 있습니까?



답변

요약 :
솔루션 (1)

import numpy as np
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`

해결책 (2) 정렬 된 목록을 원합니다

def setdiff_sorted(array1,array2,assume_unique=False):
    ans = np.setdiff1d(array1,array2,assume_unique).tolist()
    if assume_unique:
        return sorted(ans)
    return ans
main_list = setdiff_sorted(list_2,list_1)


설명은 :
(1) 당신은 NumPy와의를 사용할 수 있습니다 setdiff1d( array1, array2, assume_unique= False).

assume_unique배열이 이미 고유한지 여부를 사용자에게 묻습니다.
인 경우 False고유 요소가 먼저 결정됩니다.
이면 True함수는 요소가 이미 고유하다고 가정하고 함수는 고유 요소 결정을 건너 뜁니다.

이러한 수율 고유 한 값 array1이이 없습니다array2. assume_unique이다 False기본적으로.

고유 한 요소 ( Chinny84응답을 기반으로 함)에 관심이 있다면 간단히 (여기서 assume_unique=False=> 기본값)을 사용하십시오.

import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"] 
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`

(2)
답변을 정렬하고 싶은 분들을 위해 커스텀 함수를 만들었습니다.

import numpy as np
def setdiff_sorted(array1,array2,assume_unique=False):
    ans = np.setdiff1d(array1,array2,assume_unique).tolist()
    if assume_unique:
        return sorted(ans)
    return ans

답을 얻으려면 다음을 실행하십시오.

main_list = setdiff_sorted(list_2,list_1)

참고 사항 :
(a) 솔루션 2 (사용자 지정 함수 setdiff_sorted)는 목록을 반환 합니다 ( 솔루션 1 의 배열 과 비교 ).

(b) 요소가 고유한지 확실하지 않은 경우 setdiff1d솔루션 A와 B 모두에서 NumPy의 기본 설정을 사용하십시오 . 합병증의 예는 무엇입니까? 참고 (c)를 참조하십시오.

(c) 두 목록 중 하나가 고유 하지 않으면 상황이 달라집니다 .
고유하지 않은
list_2: list2 = ["a", "f", "c", "m", "m"]. 있는 그대로 유지 list1: 수율 list_1 = ["a", "b", "c", "d", "e"]
기본값 설정 (두 솔루션 모두). 그러나을 설정 하면 두 솔루션 모두 . 왜? 이는 사용자가 요소가 고유하다고 가정했기 때문입니다.) 따라서 유지하는 것이 좋습니다assume_unique["f", "m"]assume_unique=True["f", "m", "m"]assume_unique기본값으로. 두 답변이 모두 정렬되어 있습니다.


답변

세트를 사용할 수 있습니다.

main_list = list(set(list_2) - set(list_1))

산출:

>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']

@JonClements의 의견에 따라 다음은 더 깔끔한 버전입니다.

>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']


답변

네이티브 메서드를 사용할 수있을 때 위의 설명이 왜 그렇게 복잡한 지 잘 모르겠습니다.

main_list = list(set(list_2)-set(list_1))


답변

다음 과 같이 목록 이해력을 사용하십시오 .

main_list = [item for item in list_2 if item not in list_1]

산출:

>>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"] 
>>> 
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']

편집하다:

아래 주석에서 언급했듯이 큰 목록으로 위의 방법은 이상적인 솔루션이 아닙니다. 이 경우 더 나은 옵션은 첫 번째 로 변환 list_1하는 것입니다 set.

set_1 = set(list_1)  # this reduces the lookup time from O(n) to O(1)
main_list = [item for item in list_2 if item not in set_1]


답변

당신은 단지 필요로하는 한 줄 용액 (수입 무시)하려면 O(max(n, m))길이의 입력에 대한 작업을 n하고 m,하지 O(n * m)작업을, 당신은에 그렇게 할 수 모듈 :itertools

from itertools import filterfalse

main_list = list(filterfalse(set(list_1).__contains__, list_2))

이는 생성시 콜백 함수를 사용하는 기능적 함수를 활용하여 콜백을 한 번 생성하고 어딘가에 저장할 필요없이 모든 요소에 대해 재사용 할 수 있도록합니다 ( filterfalse내부적으로 저장하기 때문 ). 목록 이해력과 생성기 표현이이 작업을 수행 할 수 있지만보기 흉합니다. †

한 줄에 다음과 같은 결과가 나타납니다.

main_list = [x for x in list_2 if x not in list_1]

속도 :

set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]

물론 비교가 위치를 기준으로한다면 다음과 같습니다.

list_1 = [1, 2, 3]
list_2 = [2, 3, 4]

다음을 생성해야합니다.

main_list = [2, 3, 4]

(의 값 list_2이의 동일한 인덱스에서 일치 하기 때문에 list_1), 임시 s 또는 s 를 포함하지 않는 패트릭의 대답 을 선택해야합니다 ( s가 대략 인 경우에도 간단한 동등성 검사보다 검사 당 더 높은 “상수”계수를가집니다. ) 및 작업이 다른 어떤 대답보다 적으며 문제가 위치에 민감한 경우 일치하는 요소가 일치하지 않는 오프셋에 나타날 때 유일한 올바른 해결책입니다.listsetsetO(1)O(min(n, m))

† : 한 줄로 된 목록 이해력으로 동일한 작업을 수행하는 방법은 중첩 된 루프를 남용하여 “가장 바깥 쪽”루프에서 값을 만들고 캐시하는 것입니다. 예 :

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]

이는 또한 Python 3에서 약간의 성능 이점을 제공합니다 (이제 set_1각 검사에 대해 중첩 된 범위에서 조회하는 것이 아니라 이해 코드에서 로컬 범위로 지정되기 때문입니다. Python 2에서는 Python 2에서 클로저를 사용하지 않기 때문에 list comprehensions; 그들은 그들이 사용되는 것과 같은 범위에서 작동합니다).


답변

main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]

for i in list_2:
    if i not in list_1:
        main_list.append(i)

print(main_list)

산출:

['f', 'm']


답변

나는 zip목록을 함께 요소별로 비교할 것입니다.

main_list = [b for a, b in zip(list1, list2) if a!= b]