Python 04. [Algorithm 04] 딕셔너리 (Dictionary)
딕셔너리
키/값 구조이며, 입력 순서가 유지된다. 내부적으로는 해시 테이블 (Hash Table)로 구현되어 있다. 해시할 수만 있다면 숫자, 문자, 집합까지 불변 객체를 모두 키로 사용할 수 있다. 해시 테이블의 주요 연산과 시간 복잡도는 다음과 같다.
딕셔너리의 주요 연산 시간 복잡도
| 연산 | 시간 복잡도 | 설명 |
|---|---|---|
len(a) | \(O(1)\) | - |
a[key] | \(O(1)\) | - |
a[key]=value | \(O(1)\) | - |
key in a | \(O(1)\) | - |
파이썬 3.7부터는 딕셔너리의 입력 순서가 유지된다. 하지만 그 이하의 버전일 수도 있으므로 아래와 같은 모듈을 활용하자.
collections.OrderedDict(): 입력 순서가 유지됨collections.defaultdict(): 조회 시 항상 디폴트 값을 생성해 키 오류를 방지함collections.Counter(): 요소의 값을 키로 하고 개수를 값 형태로 만들어 카운팅함
딕셔너리의 활용 방법
1
2
3
4
5
6
7
8
9
10
11
# 선언
a = dict()
a = {}
a = {'key1':'value1', 'key2':'value2'}
print(a)
# {'key1':'value1', 'key2':'value2'}
a['key3'] = 'value3'
print(a)
# {'key1':'value1', 'key2':'value2', 'key3':'value3'}
리스트에서는 존재하지 않는 인덱스를 조회할 경우 IndexError가 발생하며, 딕셔너리에서는 존재하지 않는 키를 조회할 경우 KeyError가 발생한다. 다음과 같이 try 구문으로 예외 처리를 할 수 있다.
1
2
3
4
try:
print(a['key4'])
except KeyError:
print('존재하지 않는 키')
키가 존재하는지 미리 확인해 이후 작업을 진행할 수도 있다.
1
2
3
4
if 'key4' in a:
print('존재하는 키')
else:
print('존재하지 않는 키')
딕셔너리에 있는 키/값은 for 반복문으로도 조회가 가능하다. 다음과 같이 items() 메소드를 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
for k, v in a.items():
print(k, v)
# key1 value1
# key2 value2
# key3 value3
del a['key1']
print(a)
# {'key2':'value2', 'key3':'value3'}
딕셔너리 모듈
defaultdict 객체
defaultdict 객체는 존재하지 않는 키를 조회할 경우, 에러 메시지를 출력하는 대신 디폴트 값을 기준으로 해당 키에 대한 딕셔너리 아이템을 생성해준다.
1
2
3
4
5
6
7
8
9
a = collections.defaultdict(int)
a['A'] = 5
a['B'] = 4
a
# defaultdict(<class 'int'>, {'A':5, 'B':4})
a['C'] += 1
a
# defaultdict(<class 'int'>, {'A':5, 'B':4, 'C':1})
KeyError가 발생하지 않고 디폴트인 0을 기준으로 자동으로 'C'를 생성한 후 여기에 1을 더한다.
Counter 객체
Counter 객체는 아이템에 대한 개수를 계산해 딕셔너리로 리턴하며, 다음과 같이 사용한다.
1
2
3
4
a = [1, 2, 3, 4, 5, 5, 5, 6, 6]
b = collections.Counter(a)
b
# Counter({5: 3, 6: 2, 1: 1, 2: 1, 3: 1, 4: 1})
키에는 아이템의 값이, 값에는 해당 아이템의 개수가 들어간 딕셔너리를 생성한다. 실제로는 딕셔너리를 한 번 더 래핑 (Wrapping)한 collections.Counter 클래스를 갖는다.
1
2
type(b)
# <class 'collections.Counter'>
most_common():Counter객체에서 가장 빈도수가 높은 요소를 추출하는 방법
1
2
b.most_common(2)
# [(5, 3), (6, 2)]
OrderedDict 객체
입력 그대로 순서가 유지된다.
1
2
3
4
5
6
7
collections.OrderedDict({
'banana': 3,
'apple': 4,
'pear': 1,
'orange': 2
})
# OrderedDict([('banana', 3), ('apple', 4), ('pear', 1), ('orange', 2)])