본문 바로가기

Python

3-4. 세트(Set)의 특성과 중복 제거

파이썬 세트의 특성과 중복 제거 타이틀

안녕하세요! 지난 시간에는 키(Key)와 값(Value) 쌍으로 데이터를 효율적으로 저장하는 딕셔너리(Dictionary)에 대해 알아보았습니다. 이제 순서가 있는 데이터(리스트, 튜플)와 키-값 형태의 데이터(딕셔너리)를 다루는 방법을 익히셨죠!

이번 시간에는 파이썬에서 데이터를 저장하고 관리하는 또 다른 독특한 자료구조인 **세트(Set)**에 대해 알아보겠습니다. 세트는 수학의 '집합' 개념과 매우 유사하며, 특히 중복된 요소를 허용하지 않고, 요소의 순서가 중요하지 않다는 특징을 가집니다.

그럼, 세트가 어떤 특징을 가지고 있으며, 어떻게 활용되는지 자세히 살펴볼까요?


Part 1: 세트(Set)란 무엇인가?

파이썬의 세트는 다음과 같은 특징을 가집니다.

  • 중복을 허용하지 않는다 (Unique Elements): 세트에 이미 존재하는 요소를 다시 추가하려고 하면 무시됩니다. 자동으로 중복이 제거된 상태로 유지됩니다.
  • 순서가 없다 (Unordered): 리스트나 튜플처럼 요소의 저장 순서가 유지되지 않습니다. 따라서 인덱스를 사용하여 특정 위치의 요소에 접근할 수 없습니다.
  • 변경 가능하다 (Mutable): 세트 자체는 요소를 추가하거나 삭제할 수 있습니다.
  • 세트의 요소는 변경 불가능해야 한다 (Immutable Elements): 세트 안에 들어가는 각 요소는 숫자, 문자열, 튜플처럼 변경 불가능한(immutable) 객체여야 합니다. 리스트나 딕셔너리처럼 변경 가능한(mutable) 객체는 세트의 요소가 될 수 없습니다.

1. 세트 만들기

세트는 중괄호({}) 안에 쉼표(,)로 구분하여 요소들을 나열하는 방식으로 만듭니다. 빈 세트를 만들 때는 {}가 아닌 set() 함수를 사용합니다. (빈 {}는 빈 딕셔너리가 되기 때문입니다.)

예시:

Python
 
# 파일 이름: set_creation.py

# 세트 만들기 (중복된 요소는 자동으로 제거됨)
fruits = {"사과", "바나나", "체리", "사과", "오렌지"}
numbers = {1, 2, 3, 2, 1, 4, 5}
mixed_data = {10, "Hello", 3.14, True} # 순서는 보장되지 않음

# 빈 세트 만들기 (주의: {}는 빈 딕셔너리)
empty_set = set()
# empty_dict = {} # 이건 빈 딕셔너리

print(f"과일 세트: {fruits}, 타입: {type(fruits)}")
print(f"숫자 세트: {numbers}, 타입: {type(numbers)}")
print(f"혼합 데이터 세트: {mixed_data}")
print(f"빈 세트: {empty_set}, 타입: {type(empty_set)}")

 
# 파일 이름: set_creation.py

# 세트 만들기 (중복된 요소는 자동으로 제거됨)
fruits = {"사과", "바나나", "체리", "사과", "오렌지"}
numbers = {1, 2, 3, 2, 1, 4, 5}
mixed_data = {10, "Hello", 3.14, True} # 순서는 보장되지 않음

# 빈 세트 만들기 (주의: {}는 빈 딕셔너리)
empty_set = set()
# empty_dict = {} # 이건 빈 딕셔너리

print(f"과일 세트: {fruits}, 타입: {type(fruits)}")
print(f"숫자 세트: {numbers}, 타입: {type(numbers)}")
print(f"혼합 데이터 세트: {mixed_data}")
print(f"빈 세트: {empty_set}, 타입: {type(empty_set)}")

[VS Code 터미널 출력]

파이썬 세트 생성 및 자료형 확인 예시

(참고: 세트의 출력 순서는 실행할 때마다 다를 수 있습니다. 이는 세트가 순서가 없는 자료구조이기 때문입니다.)


Part 2: 세트 요소 추가/삭제하기

세트는 변경 가능한(mutable) 자료형이므로, 요소를 추가하거나 삭제할 수 있습니다. 하지만 순서가 없으므로 인덱스를 이용한 추가/삭제는 불가능합니다.

1. 요소 추가하기 (add(), update())

  • add(item): 세트에 새로운 요소를 하나 추가합니다. 이미 존재하는 요소라면 아무 일도 일어나지 않습니다.
  • update(iterable): 다른 반복 가능한(iterable) 객체(리스트, 튜플, 다른 세트 등)의 요소들을 세트에 추가합니다.

예시:

Python
 
# 파일 이름: set_add_elements.py

my_set = {1, 2, 3}
print(f"원본 세트: {my_set}")

# add()로 요소 하나 추가
my_set.add(4)
my_set.add(2) # 이미 존재하므로 추가되지 않음
print(f"add() 후: {my_set}") # 결과: {1, 2, 3, 4} (순서는 다를 수 있음)

# update()로 여러 요소 추가
new_elements = [5, 6, 2]
my_set.update(new_elements)
print(f"update() 후: {my_set}") # 결과: {1, 2, 3, 4, 5, 6} (순서는 다를 수 있음)

# 다른 세트로 update
another_set = {6, 7, 8}
my_set.update(another_set)
print(f"다른 세트로 update() 후: {my_set}") # 결과: {1, 2, 3, 4, 5, 6, 7, 8}

 
# 파일 이름: set_add_elements.py

my_set = {1, 2, 3}
print(f"원본 세트: {my_set}")

# add()로 요소 하나 추가
my_set.add(4)
my_set.add(2) # 이미 존재하므로 추가되지 않음
print(f"add() 후: {my_set}")

# update()로 여러 요소 추가
new_elements = [5, 6, 2]
my_set.update(new_elements)
print(f"update() 후: {my_set}")

# 다른 세트로 update
another_set = {6, 7, 8}
my_set.update(another_set)
print(f"다른 세트로 update() 후: {my_set}")

[VS Code 터미널 출력]

파이썬 세트에 add와 update로 요소 추가 예시

(참고: 세트의 출력 순서는 다를 수 있습니다.)

 

2. 요소 삭제하기 (remove(), discard(), pop(), clear())

  • remove(item): 세트에서 특정 item을 삭제합니다. item이 세트 안에 없으면 KeyError가 발생합니다.
  • discard(item): 세트에서 특정 item을 삭제합니다. item이 세트 안에 없어도 오류를 발생시키지 않습니다. (remove와의 차이점!)
  • pop(): 세트에서 임의의 요소를 하나 삭제하고 그 요소를 반환합니다. 세트가 비어있으면 KeyError가 발생합니다. (세트는 순서가 없으므로 어떤 요소가 삭제될지 예측할 수 없습니다.)
  • clear(): 세트의 모든 요소를 삭제하여 빈 세트로 만듭니다.

예시:

Python
 
# 파일 이름: set_delete_elements.py

my_courses = {"Python", "Java", "C++", "HTML", "CSS"}
print(f"원본 세트: {my_courses}")

# remove()로 삭제
my_courses.remove("Java")
print(f"remove('Java') 후: {my_courses}") # 'Java' 삭제됨

# remove()로 없는 요소 삭제 시도 (오류 발생!)
# my_courses.remove("JavaScript") # KeyError: 'JavaScript'

# discard()로 삭제 (없는 요소도 오류 없이 처리)
my_courses.discard("C++")
print(f"discard('C++') 후: {my_courses}") # 'C++' 삭제됨
my_courses.discard("JavaScript") # 없는 요소 삭제 시도해도 오류 없음
print(f"discard('JavaScript') 후: {my_courses}") # 변화 없음

# pop()으로 임의의 요소 삭제
removed_course = my_courses.pop()
print(f"pop() 후: {my_courses}, 삭제된 요소: {removed_course}")

# clear()로 모든 요소 삭제
my_courses.clear()
print(f"clear() 후: {my_courses}")

 
# 파일 이름: set_delete_elements.py

my_courses = {"Python", "Java", "C++", "HTML", "CSS"}
print(f"원본 세트: {my_courses}")

# remove()로 삭제
my_courses.remove("Java")
print(f"remove('Java') 후: {my_courses}")

# remove()로 없는 요소 삭제 시도 (오류 발생!)
# my_courses.remove("JavaScript") # KeyError: 'JavaScript'

# discard()로 삭제 (없는 요소도 오류 없이 처리)
my_courses.discard("C++")
print(f"discard('C++') 후: {my_courses}")
my_courses.discard("JavaScript") # 없는 요소 삭제 시도해도 오류 없음
print(f"discard('JavaScript') 후: {my_courses}")

# pop()으로 임의의 요소 삭제
removed_course = my_courses.pop()
print(f"pop() 후: {my_courses}, 삭제된 요소: {removed_course}")

# clear()로 모든 요소 삭제
my_courses.clear()
print(f"clear() 후: {my_courses}")

[VS Code 터미널 출력]

파이썬 세트에서 remove, discard, pop, clear로 요소 삭제 예시

(참고: pop()으로 삭제되는 요소는 실행할 때마다 다를 수 있습니다.)


Part 3: 세트 연산 (집합 연산)

세트의 가장 강력한 기능 중 하나는 수학의 집합 연산을 수행할 수 있다는 것입니다.

1. 합집합 (Union) - | 또는 union()

  • 두 세트의 모든 요소를 포함하는 새로운 세트를 만듭니다. 중복된 요소는 한 번만 포함됩니다.

예시:

Python
 
# 파일 이름: set_union.py

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 합집합 연산
union_set_operator = A | B
union_set_method = A.union(B)

print(f"세트 A: {A}")
print(f"세트 B: {B}")
print(f"합집합 (A | B): {union_set_operator}")
print(f"합집합 (A.union(B)): {union_set_method}")

2. 교집합 (Intersection) - & 또는 intersection()

  • 두 세트에 모두 존재하는 요소들만을 포함하는 새로운 세트를 만듭니다.

예시:

Python
 
# 파일 이름: set_intersection.py

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 교집합 연산
intersection_set_operator = A & B
intersection_set_method = A.intersection(B)

print(f"교집합 (A & B): {intersection_set_operator}")
print(f"교집합 (A.intersection(B)): {intersection_set_method}")

3. 차집합 (Difference) - - 또는 difference()

  • 한 세트에는 있지만 다른 세트에는 없는 요소들만을 포함하는 새로운 세트를 만듭니다.

예시:

Python
 
# 파일 이름: set_difference.py

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 차집합 연산
difference_set_AB_operator = A - B # A에는 있지만 B에는 없는 요소
difference_set_AB_method = A.difference(B)

difference_set_BA_operator = B - A # B에는 있지만 A에는 없는 요소
difference_set_BA_method = B.difference(A)

print(f"차집합 (A - B): {difference_set_AB_operator}")
print(f"차집합 (A.difference(B)): {difference_set_AB_method}")
print(f"차집합 (B - A): {difference_set_BA_operator}")
print(f"차집합 (B.difference(A)): {difference_set_BA_method}")

4. 대칭 차집합 (Symmetric Difference) - ^ 또는 symmetric_difference()

  • 두 세트 중 한쪽에만 존재하는 모든 요소를 포함하는 새로운 세트를 만듭니다. (합집합 - 교집합)

예시:

Python
 
# 파일 이름: set_symmetric_difference.py

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 대칭 차집합 연산
symmetric_difference_set_operator = A ^ B
symmetric_difference_set_method = A.symmetric_difference(B)

print(f"대칭 차집합 (A ^ B): {symmetric_difference_set_operator}")
print(f"대칭 차집합 (A.symmetric_difference(B)): {symmetric_difference_set_method}")

 
# 파일 이름: set_operations.py

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

print(f"세트 A: {A}")
print(f"세트 B: {B}\n")

# 합집합 (Union)
union_set = A | B
print(f"합집합 (A | B): {union_set}")

# 교집합 (Intersection)
intersection_set = A & B
print(f"교집합 (A & B): {intersection_set}")

# 차집합 (Difference)
difference_set_AB = A - B
print(f"차집합 (A - B): {difference_set_AB}")

difference_set_BA = B - A
print(f"차집합 (B - A): {difference_set_BA}")

# 대칭 차집합 (Symmetric Difference)
symmetric_difference_set = A ^ B
print(f"대칭 차집합 (A ^ B): {symmetric_difference_set}")

[VS Code 터미널 출력]

파이썬 세트의 집합 연산 (합집합, 교집합, 차집합, 대칭 차집합) 예시

(참고: 세트의 출력 순서는 다를 수 있습니다.)

 


Part 4: 세트 활용 및 주의사항 (리스트/튜플/딕셔너리와 비교)

  • 중복 제거: 가장 흔한 용도입니다. 리스트나 다른 곳에서 중복된 데이터를 제거하고 싶을 때, 해당 데이터를 세트로 변환했다가 다시 리스트로 변환하면 쉽게 중복을 제거할 수 있습니다.
    • 예: my_list = [1, 2, 2, 3, 1], unique_list = list(set(my_list))
  • 멤버십 테스트 (속도): 특정 요소가 세트 안에 있는지 확인하는 작업(in 연산자)이 리스트보다 훨씬 빠릅니다. 많은 데이터를 대상으로 특정 요소의 존재 여부를 자주 확인해야 할 때 유리합니다.
  • 수학적 집합 연산: 두 데이터 집합 간의 공통 요소, 차이점 등을 찾아낼 때 매우 유용합니다.

세트와 다른 자료구조 비교:

특징 리스트(List 튜플(Tuple) 딕셔너리(Dictionary) 세트(Set)
순서 O (인덱스 사용) O (인덱스 사용) O (Python 3.7+ 삽입 순서) X (순서 없음)
중복 허용 O O X (키는 고유, 값은 중복 허용) X (요소는 고유)
변경 가능성 O (Mutable) X (Immutable) O (Mutable) O (Mutable)
요소 타입 제한 없음 없음 키는 불변(Immutable) 객체 요소는 불변(Immutable) 객체
선언 방법 [] () 또는 쉼표 {키:값} {} 또는 set()
 

마무리하며

이번 시간에는 파이썬의 독특한 자료구조인 **세트(Set)**에 대해 알아보았습니다. 세트는 중복을 허용하지 않고 순서가 없다는 특징 덕분에 데이터의 중복을 제거하거나, 특정 요소의 존재 여부를 빠르게 확인하거나, 수학적인 집합 연산을 수행할 때 매우 강력하게 활용됩니다.

리스트, 튜플, 딕셔너리와는 다른 세트만의 특징을 잘 이해하고, 각 자료구조가 어떤 상황에 가장 적합한지 고민하며 활용하는 것이 중요합니다.

다음 포스팅에서는 지금까지 배운 리스트, 튜플, 딕셔너리, 세트 등 다양한 자료구조들의 유용한 메서드들을 총정리하고, 마지막으로 리스트/딕셔너리 내포 표현식에 대해 알아보겠습니다.


궁금한 점이 있다면 언제든지 질문해주세요! 다음 포스팅에서 만나요!

반응형