본문 바로가기

Python

[Python] 2. 파이썬의 기본 자료형(4) - 딕셔너리(Dictionary) & 집합(Set)

728x90
반응형

 

 

[목차]

 

1. 딕셔너리(Dictionary) 만들기

 

2. 딕셔너리 사용하기

 

3. 집합(Set) 만들기

 

4. 집합 사용하기

 

 

 

  1. 딕셔너리(Dictionary) 만들기

 

먼저 딕셔너리(Dictionary)란 각각의 키(key) 값마다 하나의 값이 대응된 쌍들을 모아놓은 자료형이다. 

의미 그대로 사전에서 어떤 단어의 뜻을 찾기 위해서 해당 단어만 찾으면 되듯이 특정 값을 찾기 위해서는 대응된 key값으로 바로 찾을 수 있다는 장점이 있다. 

 

리스트는 대괄호, 튜플은 소괄호를 이용했다면 딕셔너리는 중괄호 '{ }' 를 이용해서 생성한다. 

다음은 기본적인 딕셔너리의 형태이다.

{key1: value1, key2: value2, key3: value3 ...}

이처럼 key값과 value값을 콜론(:)으로 묶어서 저장하고 쉼표로 구분 짓는다.

물론 빈 딕셔너리도 생성 가능하다. 빈 딕셔너리는 a = {} 혹은 a = dict()로 생성한다. 

 

딕셔너리의 key값에는 immutable한 자료형들만 사용 가능하고, value값은 모든 자료형을 사용할 수 있다.

즉, key에는 리스트, 딕셔너리를 사용할 수 없다. 

a = {'type': 'C++', 'num': 2, 42: 3, 3.5: [1,2,3], False: 0.5, 1: {'a':'b'}}

 

만약 리스트를 초기화할 때 key값이 중복되는 쌍이 있다면 어떻게 될까?

a = {'type':'C++', 'num':2, 42:3, 'type':'python'}

print(a) # ans : {'type':'python', 'num':2, 42:3}

 

위의 예시는 'type'이라는 key값이 여러 개 있는 경우이다. 

key값이 중복되는 원소가 있는 경우에는 제일 뒤에 있는 값이 key에 대응되고, 나머지 쌍들은 무시된다. 

 

딕셔너리에 쌍을 추가하거나 삭제도 할 수 있다. 

만약 key:value 쌍으로 'x':3 을 추가하고 싶다면 a[x] = 3과 같이 이용해주면 된다. 

이 표현법이 리스트에서는 x번째 인덱스의 원소를 3으로 바꿔주는 작업이었다면, 딕셔너리에서는 {x:3} 한쌍을 딕셔너리에 추가해주는 것이다. 

'x'라는 key값이 이미 딕셔너리 내에 존재했다면, value값을 3으로 바꿔주게 된다. 

 

딕셔너리의 원소를 삭제하는 것은 del 함수를 이용한다. 

del a[x]와 같이 이용하면 'key값이 x인 쌍을 지운다'라는 의미이다. 

따라서 원소를 추가하거나 삭제할 때는 항상 기준이 key값임을 염두해야 한다. 

 

예제 코드를 통해 이해해보자.

 

a = {'name': 'John'}

a[1] = 2
print(a) # ans : {'name': 'John', 1: 2}

a[1] = 'abc'
print(a) # ans : {'name': 'John', 1: 'abc'}

del a['name']
print(a) # ans : {1: 'abc'}

a['list'] = [1,2,3,4]
print(a) # ans : {1: 'abc', 'list': [1,2,3,4]}

 

 

 

  2. 딕셔너리 사용하기

 

딕셔너리의 키에 접근하기 위해서는 a[key]와 같이 사용해주면 된다. 리스트에서 인덱스를 넣어주는 것과 비슷하다. 

a[key]는 대응되는 value를 의미하게 된다. 

만약 key가 딕셔너리에 존재하지 않는다면 에러가 발생한다. 

 

value를 얻기 위해서 get이라는 함수를 이용할 수도 있다. 

a.get(key)와 같은 방식으로 사용하며, get 함수를 이용할 땐 key가 존재하지 않는 경우 에러가 아닌 None을 반환한다.

key가 없을 때 None이 아니라 지정한 값을 반환하고 싶다면 get(key, '값')의 형태로 사용하면 된다. 

a = {'name': 'Rebro', 4:'ab', 0:[1,2]}

print(a['name']) # ans : 'Rebro'

print(a[0]) # ans : [1, 2]

print(a[1]) # ERROR ("KeyError : 1")

print(a.get(1)) # ans : None

print(a.get(1, 'no key')) # ans : 'no key'

 

a[0]이나 a[1]이 딕셔너리의 첫 번째 원소, 두 번째 원소를 의미하는 게 아님에 주의하자. 

딕셔너리 내에 key가 1인 원소가 없기 때문에 a[1]을 출력하려고 하면 에러가 발생한다. 

 

 

딕셔너리에도 여러 함수들이 있다. 

 

1) Key, value 들로 객체 만들기

 

key와 value의 쌍으로 이루어진 딕셔너리에서 Key들만, 또는 value들만 따로 뽑아낼 수 있다. 

keys()와 values() 함수를 이용하면 key 또는 value들만을 모아서 객체를 반환한다.  

 

items 함수를 이용하면 key와 value 쌍 각각을 튜플로 묶은 객체를 반환한다.  

리스트로 이용하고 싶다면 list함수를 이용해서 객체를 리스트로 바꿔줄 수 있다. 

a = {'name': 'Rebro', 4:'ab', 0:[1,2]}

print(a.keys()) # ans : dict_keys(['name', 4, 0])

print(a.values()) # ans : dict_values(['Rebro', 'ab', [1, 2]])

print(list(a.keys())) # ans : ['name', 4, 0]

print(a.items()) # ans : dict_items([('name', 'Rebro'), (4, 'ab'), (0, [1, 2])])

 

 

2) key, value 쌍 모두 지우기

 

리스트나 튜플과 마찬가지로 clear() 함수를 이용하면 빈 딕셔너리가 된다. a.clear()로 사용한다. 

 

3) 딕셔너리의 key 개수 구하기

 

key 개수는 딕셔너리의 원소의 개수와 동일하며 이는 결국 딕셔너리의 길이와 동일하다. 따라서 len 함수를 이용해서 len(a)와 같이 이용해주면 key의 개수를 구할 수 있다. 

 

4. 딕셔너리에 key가 있는지 확인하기

 

딕셔너리에 key가 있는지 없는지 확인하고 싶다면 in 또는 not in 연산자를 사용하면 된다. 

반환 값으로는 True 또는 False, 즉 boolean 값을 가진다.

 

a = {'name': 'Rebro', 4:'ab', 0:[1,2]}

print('name' in a)  # ans : True

print(2 in a)       # ans : False    

print(3 not in a)   # ans : True

print(0 not in a)   # ans : False

 

 

  3. 집합(Set) 만들기

 

파이썬에는 집합을 표현하는 자료형이 있다. 

집합 자료형은 딕셔너리와 같이 중괄호 '{ }'를 이용하거나 set 키워드를 통해서 만들 수 있다. set()의 괄호 안에 리스트를 넣거나 문자열을 입력해서 만들 수 있다. 

정확하게 말하면 '반복 가능한 객체'를 넣을 수 있다.

 

S = {1, 2, 3, 4}

S = {'ab', 'cd'}

S = set([1, 4, 5])

S = set() #빈 set

#잘못된 사용 (딕셔너리로 선언됨)
S = {} 

 

만약 집합이 중괄호를 사용한다고 해서 빈 집합을 S = {}로 만들 수 있다고 생각할 수도 있으나, 이는 이전의 빈 딕셔너리를 생성하는 것과 동일하다.

따라서 딕셔너리로 생성이 되므로 빈 집합을 만들 때에는 반드시 set 키워드를 이용해야 한다.

 

*집합은 리스트나 딕셔너리와 달리 집합 내에 집합을 넣을 수 없다. (집합 안에 집합을 넣기 위해서는 frozenset이라는 immutable한 set을 이용해야 한다.)

 

집합(set)은 다음과 같은 중요한 특징을 가진다.

 

1. 중복을 허용하지 않는다. 

2. 순서가 없다.

 

먼저, 중복을 허용하지 않기 때문에 집합을 생성할 때 중복되는 원소가 있는 경우에는 1개를 제외하고는 모두 무시된다. 

예를 들어 S = {1, 1, 2, 2, 3}으로 집합을 생성하면 S = {1, 2, 3}으로 만들어진다. 

 

그리고 집합에는 순서가 정해져 있지 않기 때문에(unordered), 집합을 매번 출력할 때마다 원소의 순서가 다르게 나온다.

또 순서가 없으므로 리스트나 튜플처럼 집합의 원소를 위치 혹은 인덱스를 이용하여 접근할 수가 없다. 

인덱스를 이용해서 접근하고 싶다면 집합을 리스트나 튜플로 바꾼 후 접근해야 한다. 

 

S = set("hello")

print(S) # ans : {'e', 'o', 'l', 'h'}

print(S[1]) #ERROR ('set' object does not support indexing)

S = {1, 1, 1, 2}

print(S) # ans : {1, 2}

L = list(S)

print(L[0]) # ans : 1

 

 

위의 예시와 같이 "hello" 문자열을 이용해서 집합을 생성하면 l이 중복되므로 하나만 들어가게 된다. 

 

 

  4. 집합 사용하기

 

1. 교집합, 합집합, 차집합 구하기

 

수학에서 쓰이는 집합을 생각해보면 기본적으로 떠오르는 연산이 교집합, 합집합, 차집합일 것이다. 

파이썬에서는 이를 아주 편하게 구할 수 있다.

 

교집합은 &(and) 기호 또는 insersection함수, 합집합은 |(or) 기호 또는 union함수, 차집합은 -(minus) 기호 또는 difference함수를 이용해서 구할 수 있다. 

두 집합에서 교집합을 뺀 대칭 차집합은 ^(xor) 기호 또는 set.symmetric_difference함수를 이용한다.

예시를 보면 충분히 이해가 될 것이다. 

 

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1 & s2)  # {4, 5, 6}
print(s1.intersection(s2)) # {4, 5, 6}
print(s2.intersection(s1))

print(s1 | s2)      # {1, 2, 3, 4, 5, 6, 7, 8}
print(s1.union(s2)) # {1, 2, 3, 4, 5, 6, 7, 8}
print(s2.union(s1))

print(s1 - s2)  # {1, 2, 3}
print(s2 - s1)  # {7, 8}
print(s1.difference(s2)) # {1, 2, 3}
print(s2.difference(s1)) # {7, 8}

print(s1 ^ s2) # {1, 2, 3, 7, 8}
print(set.symmetric_difference(s1, s2))

 

 

2. 집합에 원소 추가 제거

 

원소 1개를 집합에 추가하고 싶다면 add함수를 이용할 수 있다. 

만약 여러 원소를 추가하고 싶다면 update함수를 이용하면 된다. 

또는 앞에서 언급한 합집합 기호를 이용할 수도 있다. 추가하고 싶은 원소들로 하나의 집합을 만든 후, 기존의 집합과 합집합 연산을 하게 되면 결국 원소를 추가하는 것과 동일하다. 

 

S = {1, 2, 3}

S.add(4)   # S = {1, 2, 3, 4}

S.update([0, 6]) # S = {0, 1, 2, 3, 4, 6}

S.update({0, 6})

S = S | {1, 8, 10} # S = {0, 1, 2, 3, 4, 6, 8, 10}

 

원소 하나를 제거하고 싶다면 remove 함수 또는 discard 함수를 이용해주면 된다. 만약 제거하려는 원소가 집합에 없다면 remove 함수는 에러를 발생시키고, discard는 그냥 넘어간다.

 

임의의 원소 하나를 반환하고 싶다면 pop 함수를 사용할 수 있다. 만약 집합이 이미 빈 집합이라면 에러를 발생시킨다.

 

S = {1, 2, 3, 4}

S.remove(4) # S = {1, 2, 3}

S.discard(2) # S = {1, 3}

S.pop() # S = {1} or {3}

S.remove(5) # ERROR

 

 

 

PC로 보시는 것을 권장합니다. 

피드백은 언제나 환영입니다. 댓글로 달아주세요 ^-^

728x90
반응형