파이썬 차집합과 대칭차집합: -와 ^는 무엇이 다를까

이 카테고리 글 목록

전체글 보기

첫 집합에만 있는 값을 찾으려면 a - b, 두 집합 중 어느 한쪽에만 있는 값을 모두 찾으려면 a ^ b를 쓰세요. 차집합은 어느 쪽에서 빼는지가 중요하고, 대칭차집합은 양쪽에 공통으로 있는 값을 제외합니다.

아래는 두 가상 과일 목록을 집합으로 표현한 예입니다. sorted()는 출력 순서를 일정하게 보여주기 위해 썼습니다.

a = {"배", "자두", "사과"}
b = {"자두", "복숭아"}

print("a에만", sorted(a - b))
print("b에만", sorted(b - a))
print("한쪽에만", sorted(a ^ b))
print("양쪽에", sorted(a & b))
a에만 ['배', '사과']
b에만 ['복숭아']
한쪽에만 ['배', '복숭아', '사과']
양쪽에 ['자두']

차집합은 한쪽만, 대칭차집합은 양쪽의 남은 값

a - b에서는 a에 있던 배·자두·사과 중 b에도 있는 자두를 뺍니다. 그래서 배와 사과만 남습니다. 반대로 b - a에서는 복숭아만 남습니다.

a ^ b는 이 두 결과를 합친 집합과 같습니다. 배·사과는 a에만, 복숭아는 b에만 있으므로 세 종류가 모두 남습니다. 자두는 양쪽에 있어서 빠집니다. 따라서 a ^ b와 b ^ a는 같지만, a - b와 b - a는 달라질 수 있습니다.

두 연산의 결과는 새 집합입니다. 입력 집합을 직접 바꾸는 difference_update() 같은 메서드와 구분하세요.

리스트의 순서와 중복 횟수가 필요하면

집합은 어떤 값이 있는지를 다룹니다. 같은 배가 두 번 있어도 한 원소로 취급하고, 입력의 첫 등장 순서를 보존하는 용도로 쓰지 않습니다. 왼쪽 리스트의 순서와 남은 항목의 중복 횟수를 유지하려면, 오른쪽의 소속 여부만 집합으로 검사할 수 있습니다.

left = ["배", "배", "자두", "사과"]
right = ["자두", "복숭아"]
right_set = set(right)

print("종류만", sorted(set(left) - right_set))
print("순서와 횟수", [fruit for fruit in left if fruit not in right_set])
종류만 ['배', '사과']
순서와 횟수 ['배', '배', '사과']

두 번째 결과에는 왼쪽에 있던 배 두 개가 그대로 남습니다. 이 필터는 오른쪽에 한 번이라도 있는 값을 왼쪽에서 모두 제외합니다. 양쪽의 등장 횟수를 하나씩 빼는 계산은 아닙니다. 처음 나온 순서를 지키면서 중복을 한 번씩만 남기려는 작업은 리스트 중복 제거와 순서 보존에서 따로 다룹니다.

연산자에 리스트를 바로 넣지는 않기

-와 ^의 두 피연산자는 집합이어야 합니다. 예를 들어 집합에서 리스트를 바로 빼는 a - ["자두"]는 TypeError를 냅니다. 리스트를 set(...)으로 바꾸거나, 반복 가능한 입력을 받는 a.difference(["자두"])처럼 메서드를 사용할 수 있습니다.

집합의 원소는 해시 가능해야 합니다. 이 글의 문자열 과일 이름은 가능하지만, 리스트 자체를 원소로 넣으면 오류가 납니다. 중첩 자료라면 무엇을 같은 항목으로 볼지부터 정해야 합니다.

예제는 가상 입력이며 Windows 11의 Python 3.14.3에서 각 코드 블록을 독립 실행했습니다. 연산의 의미는 Python 집합 안내, 메서드가 받는 입력은 difference 문서에서 확인할 수 있습니다.

이 카테고리의 다른 글

전체글 보기

댓글 남기기