두 목록 간의 공통 요소 비교


143
def common_elements(list1, list2):
    """
    Return a list containing the elements which are in both list1 and list2

    >>> common_elements([1,2,3,4,5,6], [3,5,7,9])
    [3, 5]
    >>> common_elements(['this','this','n','that'],['this','not','that','that'])
    ['this', 'that']
    """
    for element in list1:
        if element in list2:
            return list(element)

지금까지는 얻었지만 작동하지 않는 것 같습니다!

어떤 아이디어?


1
안녕하세요, 코드 사용 방법에 대한 세부 정보를 추가 할 수 있습니까? 할당을 완료하려면 "Pythonic"방식을 캡슐화하는 솔루션을 선택하는 것이 좋습니다. 그러나 효율성이 우려되는 경우 "Pythonic"방식이 가장 효율적인 솔루션이 아닐 수 있습니다. 이러한 세부 사항에 대해 조언하면 솔루션이 문제를 해결하는 데 도움이됩니다.
Matt C

답변:


278
>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]

1
+1 그러나 개인적으로 나는 불변이기 때문에 frozenset을 사용 했으므로 사전 키 등으로 사용할 수 있습니다
zebrabox

19
이것은 / unique / 공통 요소를 반환하지만 존재하는 반복되는 요소는 반환하지 않습니다.
Dologan

@SilentGhost. 두 목록에서 일치하는 요소 수를 얻는 방법 이 경우 2입니다.
Poka

@Poka len (list (set (list1) .intersection (list2)))
Dharmanshu Kamra

2
참고로 이것은 Tamás가 제안한 솔루션보다 확실히 빠르지만이 페이지에서 끝낼 때보 고있는 유스 케이스의 경우 사후 필터링 된 요소의 요소의 원래 순서를 유지하는 것이 중요했습니다. 이 방법은 순서를 잃는 반면 목록 이해 방법은 순서를 유지합니다. 누군가 이것을 고려해야 할 경우 중요합니다. 감사.
apttrading

41

세트를 사용하고 한 줄로 공통점을 얻을 수도 있습니다. 세트 중 하나의 차이점을 포함하는 세트를 빼십시오.

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))

4
이로 인해 A가 두 번 설정되어 불필요하게 낭비됩니다.
wim

36

제안한 솔루션 S.MarkSilentGhost은 그것이 파이썬 방식으로 수행하는 방법을 일반적으로 말해,하지만 난 당신의 솔루션은 작업을하지 않는 이유를 알고부터 당신은 또한 혜택을 누릴 수있다 생각했다. 문제는 두 목록에서 첫 번째 공통 요소를 찾으면 해당 단일 요소 만 반환한다는 것입니다. result목록 을 작성하고 해당 목록의 공통 요소를 수집하여 솔루션을 수정할 수 있습니다 .

def common_elements(list1, list2):
    result = []
    for element in list1:
        if element in list2:
            result.append(element)
    return result

목록 이해를 사용하는 더 짧은 버전 :

def common_elements(list1, list2):
    return [element for element in list1 if element in list2]

그러나 내가 말했듯이 이것은 매우 비효율적 인 방법입니다. 파이썬의 내장 세트 유형은 내부적으로 C로 구현 될 때보 다 효율적입니다.


1
두 제안 모두에 적합
dlewin

1
참고 : 위의 방법은 동일한 크기의 목록에서만 작동합니다. 동일하지 않은 크기의 목록으로 작업하는 경우 함수를 호출하기 전에 len ()을 기준으로 순서를 평가해야합니다. list1 = [2,2,2], list2 [2,3]-> [2,2,2] list1 = [2,3], list2 [2,2,2]-> [2]
redthumb

29

집합 교차점 사용, set (list1) & set (list2)

>>> def common_elements(list1, list2):
...     return list(set(list1) & set(list2))
...
>>>
>>> common_elements([1,2,3,4,5,6], [3,5,7,9])
[3, 5]
>>>
>>> common_elements(['this','this','n','that'],['this','not','that','that'])
['this', 'that']
>>>
>>>

결과 목록은 원본 목록과 순서가 다를 수 있습니다.


도와 주셔서 감사합니다. 내가 잘못한 부분과 다음에해야 할 일을 이해하십시오. :)
Daniel

5
훌륭한 솔루션. 이것으로 질서를 유지하는 방법이 있습니까?
tarrasch

14

간단한 목록 이해를 사용할 수 있습니다.

x=[1,2,3,4]
y=[3,4,5]
common = [i for i in x if i in y]
common: [3,4]

9

세트는 우리가 이것을 해결할 수있는 또 다른 방법입니다

a = [3,2,4]
b = [2,3,5]
set(a)&set(b)
{2, 3}

9

list1 = [1,2,3,4,5,6] list2 = [3,5,7,9]

나는 이것을 해결할 수있는 3 가지 방법을 알고 있습니다. 물론 더있을 수 있습니다.

1-

common_elements = [e for e in list1 if e in list2]

2-

import numpy as np
common_elements = np.intersect1d(list1, list2)

삼-

common_elements = set(list1).intersection(list2)

세트가 해시 테이블을 사용하여 구현되므로 세 번째 방법이 가장 빠릅니다.


8

이전 답변은 모두 고유 한 공통 요소를 찾기 위해 작동하지만 목록에서 반복되는 항목을 설명하지 못합니다. 공통 요소가 목록에서 공통으로 발견되는 것과 동일한 번호로 표시되도록하려면 다음 단일 라이너를 사용할 수 있습니다.

l2, common = l2[:], [ e for e in l1 if e in l2 and (l2.pop(l2.index(e)) or True)]

or True요소는 평가할 요소가있는 경우에만 필요합니다 False.


굉장한 해결책이라면, 가장 철저한 것 같습니다
Hendeca

이 답변을 선택해야합니다! 나는 그것이 목록이 같지 않다고 가정합니다. 또한 대부분의 솔루션 사용 set은 안정적이지 않습니다 (일명 주문이 손실 됨).
lifebalance

7

각 답변에서 언급 한 각 방법을 비교했습니다. 현재이 구현에는 Python 3.6.3을 사용합니다. 이것은 내가 사용한 코드입니다.

import time
import random
from decimal import Decimal


def method1():
    common_elements = [x for x in li1_temp if x in li2_temp]
     print(len(common_elements))


def method2():
    common_elements = (x for x in li1_temp if x in li2_temp)
    print(len(list(common_elements)))


def method3():
    common_elements = set(li1_temp) & set(li2_temp)
    print(len(common_elements))


def method4():
    common_elements = set(li1_temp).intersection(li2_temp)
    print(len(common_elements))


if __name__ == "__main__":
    li1 = []
    li2 = []
    for i in range(100000):
        li1.append(random.randint(0, 10000))
        li2.append(random.randint(0, 10000))

    li1_temp = list(set(li1))
    li2_temp = list(set(li2))

    methods = [method1, method2, method3, method4]
    for m in methods:
        start = time.perf_counter()
        m()
        end = time.perf_counter()
        print(Decimal((end - start)))

이 코드를 실행하면 list 나 generator를 사용하면 (제너레이터를 반복하는 경우 그냥 사용하지 말고 생성기를 강제로 인쇄 할 때이 작업을 수행 한 경우) 거의 동일한 성능을 얻을 수 있습니다. 그러나 set을 사용하면 성능이 훨씬 향상됩니다. 또한 교차 방법을 사용하면 성능이 약간 향상됩니다. 내 컴퓨터의 각 방법의 결과는 다음과 같습니다.

  1. 방법 1 : 0.8150673999999999974619413478649221360683441
  2. 방법 2 : 0.8329545000000001531148541289439890533685684
  3. 방법 3 : 0.0016547000000000089414697868051007390022277
  4. 방법 4 : 0.0010262999999999244948867271887138485908508

5

이것은 내 제안입니다 for 루프보다 세트로 더 쉽다고 생각합니다.

def unique_common_items(list1, list2):
   # Produce the set of *unique* common items in two lists.
   return list(set(list1) & set(list2))

2

왜 사용하지 list comprehension않습니까?

하프 라인 솔루션 :

common_elements = [x for x in list1 if x in list2]

0

1) 방법 1 저장 list1은 사전이며 list2의 각 요소를 반복합니다.

def findarrayhash(a,b):
    h1={k:1 for k in a}
    for val in b:
        if val in h1:
            print("common found",val)
            del h1[val]
        else:
            print("different found",val)
    for key in h1.iterkeys():
        print ("different found",key)

공통 요소와 다른 요소 찾기 :

2) set2를 이용한 Method2

def findarrayset(a,b):
    common = set(a)&set(b)
    diff=set(a)^set(b)
    print list(common)
    print list(diff) 

-1

발전기를 사용하십시오 :

common = (x for x in list1 if x in list2)

여기서 큰 장점은 거대한 목록이나 다른 거대한 iterable을 사용하는 경우에도 일정한 시간 (거의 거의)에 반환된다는 것입니다.

예를 들어

list1 =  list(range(0,10000000))
list2=list(range(1000,20000000))
common = (x for x in list1 if x in list2)

여기의 다른 모든 답변은 list1 및 list2에 대한 이러한 값으로 시간이 오래 걸립니다.

그런 다음 답변을 반복 할 수 있습니다

for i in common: print(i)

또는 다음을 사용하여 목록으로 변환하십시오.

list(i)

이것은 답변을 제공하지 않습니다. 결과는 공통 ​​요소 목록이 아닌 생성기입니다.
josiekre

1
맞습니다. 발전기를 만듭니다. 문제는 어떻게 든이 생성기가하는 두 목록의 공통 요소를 얻는 것이 었습니다. 다음과 같이 생성기를 간단히 반복하십시오 for i in common: print(i). 제너레이터는리스트와 같은 다른 이터 러블 대신에 자주 사용되는 이터 러블입니다.
cowlinator 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.