[파이썬] 딕셔너리(dict)와 집합(set)

I. 딕셔너리 (dict)

  • 딕셔너리는 키와 값으로 구성된 자료 구조
  • 파이썬에서는 저장 도구로 딕셔너리를 자주 사용
  • 검색 기준은 키(key)로 저장, 키 값은 내부적으로 해시로 변환
  • 해시 변환 가능한 객체로는 숫자, 문자열 등 변경 불가 객체 사용

가. 일반 딕셔너리

  • [예제] 딕셔너리 객체 생성 및 확인
dictA = {'a' : 1, 'b' : 2}
print(type(dictA))

dictA['a'] = 10

print(dictA)

for key in dictA.keys() :   # 딕셔너리의 키만 조회할 때 keys 메소드 사용
    print(key)

for value in dictA.values() :   # 딕셔너리의 값만 조회할 때 values 메소드 사용
    print(value)

for key, value in dictA.items() :   # 딕셔너리의 키/값 쌍 조회 시 items 메소드 사용
    print("key:", key, ", value:", value)

print(dictA.get('c', "키 없음"))   # 없는 키 검색 시 예외 처리

[결과]
<class 'dict'>
{'a': 10, 'b': 2}
a
b
10
2
key: a , value: 10
key: b , value: 2
키 없음
  • [예제] 딕셔너리 업데이트
dictA = {'a' : 1, 'b' : 2}
dictB = {'c' : 3}

dictA.update(dictB) # dictA 딕셔너리 변수에 dictB 추가
print(dictA)

dictAcopy = dictA.copy()    # dictA 딕셔너리 사본 생성

dictAcopy['d'] = dictB  # 딕셔너리 사본에 키(d)/값(dictB) 추가
print(dictAcopy)

dictAcopy['d']['c'] = 300   # 딕셔너리 내 딕셔너리의 값 변경
print(dictAcopy)

[결과]
{'a': 1, 'b': 2, 'c': 3}
{'a': 1, 'b': 2, 'c': 3, 'd': {'c': 3}}
{'a': 1, 'b': 2, 'c': 3, 'd': {'c': 300}}

나. 순서 딕셔너리

  • 파이썬 딕셔너리는 순서 유지 안하므로 순서 유지 필요 시 OrderedDict 클래스 사용
  • [예제] 순서 딕셔너리 사용
import collections as cols

dictA = {'a' : 1, 'b' : 2}

orderedDictA = cols.OrderedDict(dictA) # 순서 딕셔너리 필요 시 이 클래스로 객체 생성

orderedDictA['c'] = 3
orderedDictA.update({'d' : 10})

print(orderedDictA)

[결과]
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 10)])
  • 순서 딕셔너리 사용 시 ‘OrderedDict’가 붙음

 

II. 집합 (set)

가. 집합 (set)

  • 리터럴 표기법으로 중괄호 사용
  • 변경 불가능한 집합 객체인 frozenset으로 변환
  • [예제] 집합 사용하기
setA = {1, 2, 3, 4, 5}
fsetA = frozenset(setA)
print(setA, fsetA)

setA.add(6)     # 원소 추가
print("교집합:", setA.intersection(fsetA)) # 교집합
print("합집합:", setA.union(fsetA))        # 합집합

setB = {1, 2, 3, 2, 1}  # 집합(set)은 유일한 원소값만 가지므로 중복 시 하나의 값으로 처리
print("중복 원소 제거:", setB)

setB.discard(3)         # 원소 삭제
setB.remove(2)          # 원소 삭제
print("삭제 후:", setB)

setA.difference_update(setB)    # 차집합 수행 결과로 내부 원소 변경
print("차집합 결과로 원소 변경:", setA)

setA.update({10})       # 원소 추가
print("원소 추가:", setA)

[결과]
{1, 2, 3, 4, 5} frozenset({1, 2, 3, 4, 5})
교집합: {1, 2, 3, 4, 5}
합집합: {1, 2, 3, 4, 5, 6}
중복 원소 제거: {1, 2, 3}
삭제 후: {1}
차집합 결과로 원소 변경: {2, 3, 4, 5, 6}
원소 추가: {2, 3, 4, 5, 6, 10}

나. 다중집합 (multi-set)

  • 같은 원소를 가질 수 있는 집합
  • [예제] 다중집합 사용하기
import collections as cols

msetA = [1, 1, 2, 2, 3, 3, 3]       # 다중집합은 대괄호([, ]) 사용
countMsetA = cols.Counter(msetA)    # 다중집합 원소 개수 카운트
print("다중집합 카운트:", countMsetA)
print("2의 원소 개수:", countMsetA[2])

countMsetB = countMsetA + countMsetA
print("다중집합 덧셈연산:", countMsetB)

countMsetC = countMsetB - countMsetA
print("다중집합 뺄셈연산:", countMsetC)

[결과]
다중집합 카운트: Counter({3: 3, 1: 2, 2: 2})
2의 원소 개수: 2
다중집합 덧셈연산: Counter({3: 6, 1: 4, 2: 4})
다중집합 뺄셈연산: Counter({3: 3, 1: 2, 2: 2})

 

III. Heap 자료구조

  • Heap은 자료 저장 후 필요 시 마다 꺼내서 사용 가능
  • [예제] Heap 자료구조 사용하기
class Heap :
    def __init__(self) :
        self._dict = {}
    def empty(self) :
        return True if len(self._dict) == 0 else False
    def pop(self, key) :                # 저장소에서 원소 추출
        if self._dict.get(key, 0) :     # get 메소드는 예외 발생하지 않음
            return self._dict.pop(key)
        else :
            return 0
    def push(self, key, value) :
        return self._dict.setdefault(key, value)    # setdefault는 키가 없으면 키/값 저장 후 조회, 키가 있으면 조회
    def getHeap(self) :
        return self._dict.copy()

h = Heap()
print("empty 확인:", h.empty())

h.push("국어", 90)   # 원소 하나 추가
h.push("수학", 80)  # 원소 하나 추가

print("Heap 원소 확인:", h.getHeap())

h.pop("국어")        # 원소 하나 제거
print("Heap 원소 확인:", h.getHeap())

h.pop("수학")        # 원소 하나 제거
print("Heap 원소 확인:", h.getHeap())

[결과]
empty 확인: True
Heap 원소 확인: {'국어': 90, '수학': 80}
Heap 원소 확인: {'수학': 80}
Heap 원소 확인: {}

 

[참고]

  • 잇플, “한 권으로 개발자가 원하던 파이썬 심화 A to Z”, 2019.11

콘텐츠 사용 시 출처 표기 부탁 드리고, 댓글은 큰 힘이 됩니다^^