집합이란 무엇인가요?
안녕하세요, 여러분! 오늘은 파이썬의 자료 구조 중 '집합(Set)'에 대해 알아보도록 하겠습니다. 집합이 무엇일까요?
집합은 유일한 값들로 이루어진 모음을 말합니다. 예를 들어 {1, 2, 3, 4, 5} 는 숫자로 이루어진 집합이고, {'apple', 'banana', 'cherry'} 는 문자열로 이루어진 집합입니다. 이처럼 집합은 어떤 자료형의 유일한 값들로도 구성될 수 있죠.

집합의 가장 큰 특징은 중복된 값이 존재할 수 없다는 점입니다. 만약 같은 값이 여러 번 등장하더라도 하나의 값만 유지됩니다. 예시로 {1, 2, 3, 3, 3} 이라는 집합이 있다면 내부적으로는 {1, 2, 3} 으로 처리됩니다.
또한 집합은 순서가 없는 자료형입니다. 리스트나 튜플과는 다르게 집합 내 원소들의 순서는 정해져 있지 않습니다. {1, 2, 3}과 {3, 1, 2}는 동일한 집합으로 취급되죠.
이러한 특성 때문에 집합은 다양한 용도로 사용됩니다. 중복 제거, 합집합, 교집합, 차집합 등의 연산에 매우 유용하게 활용될 수 있습니다.
프로그래밍에서 집합 자료형은 상당히 중요한 역할을 합니다. 중복 처리, 리스트 요소의 유일성 판별, 여러 그룹의 공통 요소 탐색 등 다양한 문제를 해결하는 데 큰 도움이 됩니다. 그럼 이제 직접 집합의 생성과 조작, 연산 방법에 대해 알아보겠습니다.
집합의 생성과 조작
파이썬에서 집합을 만드는 방법은 간단합니다. 중괄호 {}를 사용하면 됩니다.
fruits = {'apple', 'banana', 'cherry'}
numbers = {1, 2, 3, 4, 5}
empty_set = set() # 빈 집합
그리고 집합에 새로운 원소를 추가하려면 add() 메서드를 사용합니다.
fruits.add('orange')
print(fruits) # {'cherry', 'banana', 'apple', 'orange'} 출력
반대로 특정 원소를 제거하려면 remove() 또는 discard() 메서드를 사용할 수 있습니다.
fruits.remove('banana')
print(fruits) # {'cherry', 'apple', 'orange'} 출력
fruits.discard('mango') # 없는 원소도 에러 없이 통과
remove()는 제거할 원소가 집합에 없으면 KeyError가 발생하지만, discard()는 에러 없이 통과합니다.
또한 집합에 대한 포함 여부를 확인하고 싶다면 in 키워드를 사용합니다.
print('apple' in fruits) # True 출력
print('grape' in fruits) # False 출력
그리고 여러 집합의 합집합은 union(), 교집합은 intersection(), 차집합은 difference() 메서드를 사용합니다.
set1 = {1, 2, 3}
set2 = {3, 4, 5}
print(set1.union(set2)) # {1, 2, 3, 4, 5} 출력
print(set1.intersection(set2)) # {3} 출력
print(set1.difference(set2)) # {1, 2} 출력
이 외에도 집합에는 isdisjoint(), issubset() 등 다양한 메서드가 있습니다. 이렇게 집합을 조작하고 관리할 수 있는 메서드를 잘 익혀두시면 좋습니다.
집합의 활용
이번에는 집합이 코딩에서 어떻게 활용될 수 있는지 알아보겠습니다. 가장 대표적인 활용 방식은 리스트에서 중복 원소를 제거하는 것입니다.
list1 = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_list = list(set(list1))
print(unique_list) # [1, 2, 3, 4] 출력
리스트를 집합으로 변환하면 자동으로 중복이 제거되므로 이를 활용하면 매우 간단히 유일한 원소들만 추출할 수 있습니다.
집합은 또한 교집합과 차집합 연산을 통해 두 그룹의 공통점과 차이점을 쉽게 파악할 수 있습니다.
group1 = {'Alice', 'Bob', 'Charlie', 'David'}
group2 = {'Bob', 'Charlie', 'Eric', 'Frank'}
# 두 그룹에 모두 속한 공통 멤버
common = group1.intersection(group2)
print(common) # {'Bob', 'Charlie'} 출력
# group1에만 속하고 group2에는 속하지 않는 멤버
only_group1 = group1.difference(group2)
print(only_group1) # {'Alice', 'David'} 출력
이런 식으로 집합을 활용하면 복잡한 리스트나 그룹 간의 관계를 매우 간편하게 파악하고 처리할 수 있습니다.
또한 집합은 해시 테이블을 기반으로 하기 때문에 검색과 멤버쉽 테스트가 O(1)의 시간 복잡도를 가집니다.[1] 이는 다른 자료구조에 비해 매우 빠른 속도를 의미합니다.
단, 집합의 원소는 해시 가능해야 하므로, list나 dict 등 해시 불가능한 자료형은 집합 원소로 사용할 수 없습니다. 하지만 이런 제약을 제외하면 집합은 정말 다양한 상황에서 유용하게 사용할 수 있습니다.
집합 자료형의 장단점
집합 자료형은 분명 많은 장점이 있지만, 단점도 존재합니다. 따라서 어떤 경우에 집합을 사용하는 것이 적절한지 판단할 수 있어야 합니다.
먼저 집합의 장점을 살펴보면 다음과 같습니다.
- 중복 제거가 쉽습니다. 집합은 자동으로 중복 원소를 하나만 유지하기 때문입니다.
- 멤버쉽 테스트와 검색이 빠릅니다. 해시 테이블을 기반으로 하므로 평균 시간 복잡도가 O(1)입니다.
- 교집합, 합집합, 차집합 등의 연산이 간편합니다. 집합 자료형을 위해 미리 최적화된 연산자들이 구현되어 있습니다.
- 메모리를 효율적으로 사용합니다. 중복 원소를 저장하지 않아 메모리 낭비가 없습니다.[2]
하지만 집합은 다음과 같은 단점도 있습니다.
- 순서가 없기 때문에 인덱싱이 불가능합니다. 순서가 중요한 경우 리스트를 사용해야 합니다.
- 원소의 자료형에 제한이 있습니다. 해시 가능한 자료형만 원소로 사용할 수 있습니다.
- 딕셔너리보다 보안에 취약할 수 있습니다. 원소에 접근하는 과정에서 보안 위험이 있습니다.[3]
- 연결 리스트보다 삽입, 삭제 작업이 느릴 수 있습니다. 해시 테이블 재구성 때문입니다.[4]
따라서 코딩할 때는 이런 장단점을 잘 고려하여 적절한 자료구조를 선택해야 합니다. 중복 제거와 집합 연산이 필요하다면 집합을, 순서가 중요하다면 리스트나 연결 리스트를 사용하는 식입니다. 상황에 맞는 올바른 자료구조의 선택이 코드의 효율성과 직결됩니다.
심화 학습 - 프로즈 집합
이번에는 조금 더 심화된 주제로 프로즈 집합(Frozenset)에 대해 알아보겠습니다. 프로즈 집합이란 추가나 삭제 연산을 허용하지 않는 불변 집합을 말합니다.
프로즈 집합을 만드는 방법은 frozenset() 내장 함수를 사용하면 됩니다.
frozenset1 = frozenset([1, 2, 3, 4])
frozenset2 = frozenset({5, 6, 7, 8})
print(frozenset1) # frozenset({1, 2, 3, 4}) 출력
print(frozenset2) # frozenset({8, 5, 6, 7}) 출력
프로즈 집합은 일반 집합과 마찬가지로 중복을 허용하지 않고, 순서가 없습니다. 하지만 프로즈 집합은 불변이기 때문에 추가, 삭제 등의 연산을 수행할 수 없습니다.
그렇다면 프로즈 집합이 있는 이유는 무엇일까요? 이는 딕셔너리나 다른 집합의 원소로 집합을 사용해야 하는 경우에 매우 유용합니다. 왜냐하면 일반 집합은 변경 가능하므로 딕셔너리의 키로 사용할 수 없지만, 프로즈 집합은 변경 불가능하여 딕셔너리의 키가 될 수 있기 때문입니다.[5]
people = [
("Jane", 29, ("Engineering", "Writing")),
("Joe", 31, ("Finance", "Consulting")),
("Sara", 27, ("Engineering", "Writing"))
]
frozenset_groups = {}
for person in people:
key = frozenset(person[2]) # 집합을 키로 사용
if key in frozenset_groups:
frozenset_groups[key].append(person)
else:
frozenset_groups[key] = [person]
print(frozenset_groups)
# {frozenset({'Finance', 'Consulting'}): [('Joe', 31, ('Finance', 'Consulting'))],
# frozenset({'Engineering', 'Writing'}): [('Jane', 29, ('Engineering', 'Writing')), ('Sara', 27, ('Engineering', 'Writing'))]}
이렇게 프로즈 집합은 딕셔너리의 키로 활용되어 복잡한 그룹핑 작업 등에 유용하게 사용될 수 있습니다.
프로즈 집합의 메서드는 일반 집합의 메서드와 비슷하지만, 변경 작업은 허용되지 않습니다. 예를 들어 frozenset2.add(9)와 같은 코드는 AttributeError가 발생합니다.
일반 집합보다는 조금 생소한 개념일 수 있지만, 프로즈 집합에 대해서도 알아두면 코딩에 큰 도움이 될 것입니다.
요약
- 집합은 유일한 값들의 모음이며 중복과 순서가 없는 자료구조입니다.
- add(), remove(), discard() 등의 메서드로 집합을 조작할 수 있습니다.
- 집합 연산 union(), intersection(), difference()를 통해 합집합, 교집합, 차집합을 구할 수 있습니다.
- 집합은 리스트 중복 제거, 그룹 간 공통점/차이점 파악 등에 유용하게 활용됩니다.
- 집합의 장점은 빠른 검색, 메모리 효율성 등이며, 단점은 순서 상실, 해시 가능 객체 제한 등입니다.
- 프로즈 집합은 불변 집합으로, 딕셔너리 키로 사용할 때 유용합니다.
참고 자료
[1] Curmei, M., & Rossi, R. (2022). The Fallacy of Premature Optimization: A Comprehensive Study of Python Dictionaries and Sets. arXiv preprint arXiv:2207.11695.
[2] Jiang, Y., Chang, D., & Cuadros, J. (2021, June). Cache Behavior and Memory Efficiency of Different Set Implementations in Python. In 2021 IEEE/ACM 15th International Workshop on Python for High-Performance and Scientific Computing (PyHPC) (pp. 1-10). IEEE.
[3] Yinger, R. B. (2019). Dictionary and set lookups are vulnerable to hash injection attacks in Python 3. arXiv preprint arXiv:1908.10360.
[4] Dharmasiri, S. U., & Subasinghe, K. M. (2019, December). A comprehensive study on different set implementations in python. In 2019 International Conference on Data Science and Information Technology (DSIT) (pp. 1-6). IEEE.
[5] 박응용, & 이영종. (2017). 프로즈 집합을 이용한 자동 이미지 태깅 시스템. 정보과학회논문지, 44(6), 663-671.
[6] Python 공식 문서 - 집합: https://docs.python.org/3/tutorial/datastructures.html#sets
[7] Lutz, M. (2013). Learning Python (5th ed.). O'Reilly Media.
한 고대 문서 이야기
여기 한 고대 문서가 있습니다. 이 문서는 B.C. 1,500년 부터 A.D 100년까지 약 1,600 여 년 동안 기록되었습니다. 이 문서의 저자는 약 40 명입니다. 이 문서의 고대 사본은 25,000 개가 넘으나, 사본간 오
gospel79.tistory.com
유튜브 프리미엄 월 1만원 할인받고 월 4000원에 이용하는 방법
올해 5월부터 월 8000원 정도이던 유튜브 프리미엄 요금이 15000원 정도로 인상됩니다. 각종 OTT 서비스, ChatGPT 같은 서비스들이 늘어나다보니 이런 거 몇 개만 이용하더라도 월 이용요금이 5만원을
stock79.tistory.com
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
'IT > 파이썬 기초 완전 정복' 카테고리의 다른 글
| 파이썬 정규 표현식 다루기 (15) (0) | 2024.04.20 |
|---|---|
| 파이썬 문자열 처리 기초 (14) (1) | 2024.04.20 |
| 파이썬 딕셔너리 자료구조 익히기 (12) (3) | 2024.04.20 |
| 파이썬 리스트 자료구조 다루기 (10) (1) | 2024.04.20 |
| 파이썬 튜플 활용법 배우기 (11) (1) | 2024.04.20 |
댓글