카테고리 없음

Python - Set, Dictionary

jin_j_i_n 2022. 10. 25. 23:26

1. Set

집합은 파이썬 2.3 부터 지원하기 시작한 자료형으로, 집합에 관련된 것을 쉽게 처리하기 위해 만든 자료형이다. 

 

집합은 {} (중괄호)와 ,(컴마)를 이용해 집합을 만들 수 있다. 그러나 비어있는 중괄호는 집합이 아니라 사전(dictionary)를 만드니 주의하여야 한다.

 

s1 = set()
s2 = {}

print(type(s1)) # <class 'set'>
print(type(s2)) # <class 'dict'>

 

빈 집합은 set() 키워드를 사용하여 만들어야 한다.

 

리스트나 튜플과 달리 집합은 아이템의 순서를 유지해주지 않는다. 중복된 아이템들은 제거되고, 하나만 남는다. 시퀀스가 아니기 때문에 인덱싱이나 슬라이싱 또한 사용할 수 없다.

 

s1 = set("Hello")
s2 = set([1, 2, 3, 3, 0, -1, 9, 4, 5, 1, 1, 1])

print(s1) # {'e', 'l', 'o', 'H'}
print(s2) # {0, 1, 2, 3, 4, 5, 9, -1}

 

 

s2 출력을 보면 언뜻 정렬된 것 같지만, 파이썬의 공식 def에 따르면 set 은 unordered collection이라고 명시되어있다. 따라서 따로 정렬을 해주지 않는다는것을 짚고 넘어가야 한다. 출력된 결과만 보고 정렬까지 해주는구나 하면 안된다는 것이다.

 

1.1 list <-> set

list를 set으로 변경할 수 있고, set을 list로 변경할 수도 있다.

 

# 리스트를 셋으로 변경
l = [1, 1, 2, 2, 3, 4, 5, 6, 1, 1]
s = set(l) 

s # {1, 2, 3, 4, 5, 6}

 

# 셋을 다시 리스트로 변경 
new_l = list(s)

new_l # [1, 2, 3, 4, 5, 6]

 

1.2 집합의 연산들

 

- append , update 

 

# 집합은 순서를 유지해주지 않습니다.
s = {5, 6, 7}
s.add(1)

s # {1, 5, 6, 7}

# 여러개를 추가할 때는 update 연산을 사용
s.update([8, 9, 10])

s # {1, 5, 6, 7, 8, 9, 10 }

 

 

- in 

 

s = {5, 6, 7}

3 in s # True

 

- 집합 연산 ( | , & , - , ^ )

 

A = {0, 2, 4, 6, 8}
B = {1, 2, 3, 4, 5}
  
print("합집합 :", A | B) # A.union(B)
print("교집합 :", A & B) # A.intersection(B)
print("차집합 :", A - B) # A.difference(B)
print("대칭차집합 :", A ^ B) # A.symmetric_difference(B)

###
합집합 : {0, 1, 2, 3, 4, 5, 6, 8}
교집합 : {2, 4}
차집합 : {0, 8, 6}
대칭차집합 : {0, 1, 3, 5, 6, 8}
###

 

 

2. Dictionary

사전(dict) 자료형은 두 객체가 키(key)와 값(value)으로 짝지어져서 나열되어 있는 형태이다.
리스트나 튜플이 시퀀스로 분류가 되듯이 사전은 '매핑(mapping)' 자료형으로 분류됩니다. 여기서 매핑은 일대일 대응을 의미하고, 현재 파이썬에서 매핑으로 분류되는 기본 자료형은 Dictionary 한가지이다.
 
Set과 비슷하게 Key에 대해서는 중복을 허용하지 않는다. 하지만 파이썬 3.6 부터는 dict의 key에 대해 순서유지가 추가되었다.

 

2.1 Dictionary 생성

 

{} (중괄호) 와 , (컴마) 를 사용하는데, 이때 키(key)와 값(value)를 이용해 짝을 지어준다.

 

d = {}  # 비어있는 물결괄호는 집합이 아니라 사전입니다.
d = dict()
d = {
    "바나나": "외떡잎식물 생강목 파초과 바나나속에 속하는 식물의 총칭.",
    "아이언맨": "여심을 사로잡는 매력적인 미소의 백만장자 플레이보이 토니 스타크(Tony Stark).",
    123: 456,  # 마지막 컴마는 무시합니다. 새로 아이템을 추가할 일이 많다면 남겨두는게 편합니다.
}

# 모두 같은 dict를 만든다.
d1 = {"one": 1, "two": 2, "three": 3}
d2 = dict({"three": 3, "one": 1, "two": 2})
d3 = dict({"one": 1, "three": 3}, two=2)
d4 = dict(one=1, two=2, three=3)

# 튜플의 리스트
d5 = dict([("two", 2), ("one", 1), ("three", 3)]) # 튜플하나만으로는 dict 생성 불가

 

키가 중복될 경우에는 마지막 하나만 남는다. 집합에서 중복을 허용하지 않는 것과 비슷하다.

 

d = {
    "캡틴": "Captain",
    "캡틴": "아메리카",  # 키가 중복될 경우 마지막 하나만 남는다.
}

d # {'캡틴': '아메리카'}


# 값의 중복은 가능하다.
d = {
    "원주율": 3.141592,
    "pi": 3.141592,  # 키는 중복 X, 값은 중복 가능
}

 

2.2 Dictionary Key의 불변성

 

Key에는 불변 객체만 사용할 수 있다 (문자열, 정수, 튜플). 키가 변경되면 찾을 수 없기 때문이다.

 

# 튜플을 키로 사용 가능
d = {("캡틴아메리카", "아이언맨"): "시빌워"}

# 튜플이 키일 때 괄호를 생략하면 에러 발생  
d = {"캡틴아메리카", "아이언맨": "시빌워"} # Error 

# 리스트를 키로 사용 불가능
d = {["캡틴아메리카", "아이언맨"]: "시빌워"} # Error

# 값에 리스트를 사용하는 것은 가능
d = {"어벤져스": ["블랙위도우", "호크아이"]}

 

2.3 Dict의 사용방법

 

대괄호 안에 키(key)를 넣어서 값을 찾을 수 있다.

 

d = {
    "A": 65,
    "B": 66,
    "C": 67,
}

d["B"] # 66

# 존재하지 않는 key에 대해 value를 요청하면 에러 발생
d["b"] # Error

 

존재하지 않는 key에 대해 value를 요청하면 KeyError 가 발생한다.

이때 get() 메서드를 사용하면 에러 없이 None을 받을 수 있다.

 

# if문과 함께 사용해서 키가 존재하지 않는 경우에 대응
v = d.get("b")
if v == None:
    print("The key doesn't exist in the dict.")
else:
    print("The value is", v)

# 키가 존재하지 않는 경우 기본값을 반환하도록 설정 가능
d.get("b", "키가 존재하지 않아요.")

 

get() 함수의 두번째 인자로 Key에 대한 value가 없을 시 리턴 할 기본값을 설정할 수 있다.

 

또한 in 연산자를 통해 에러를 피하는 방법도 존재한다.

 

if "b" in d:
    print("The value is", d["b"])
else:
    print("The key doesn't exist in the dict.")

 

* 키에 float를 사용하는 것은 권장하지 않는다.

 

# 1과 1.0을 구분하지 않습니다.
d = {1: "일", 1.0: "일점영"}

d # {1: '일점영'}

# 정밀도 문제로 키를 찾지 못할 수도 있다.
d = {0.1 * 0.1: "일일일일"}

d[0.01] # KeyError: 0.01

 

Key가 튜플일 경우 값을 찾을 때 괄호를 생략할 수 있다.

 

d = {("캡틴아메리카", "아이언맨"): "시빌워"}
d["캡틴아메리카", "아이언맨"]  # 튜플을 키로 사용할 경우 괄호 생략 가능

 

2.3 Dictionary 삭제

 

delt 키워드를 사용해서 키:값 쌍을 삭제할 수 있다.

모든 쌍을 지우고 싶을땐 clear() 함수를 사용할 수 있다.

 

my_dict = {"A": 65, "B": 66, "C": 67, "D": 68}
del my_dict["A"]

my_dict # {'B': 66, 'C': 67, 'D': 68}

# 모두 지우고 싶을 때는 clear()도 사용할 수 있다.
my_dict.clear()

my_dict # {}

 

또한 del로 아예 변수를 지워버릴 수 있다.

 

to_be_deleted = {"A": 65, "B": 66, "C": 67, "D": 68}

del to_be_deleted

to_be_deleted # {}

 

2.4 다른 컨테이너들과의 용법 차이

 

dict는 키:값 쌍이라는 점에서 다른 컨테이너들과 용법이 다른부분이 있다.

 

alphabets = {"A": 65, "B": 66, "C": 67, "D": 68}

# dict를 list로 바꾸면 key만 남는다.
list(alphabets) # ['A', 'B', 'C', 'D']

 

- len과 in 도 key 기준으로 작동한다.

 

len(alphabets) # 4

"A" in alphabets # True

65 in alphabets # False

 

- keys() 메서드와 values() 메서드를 이용해 각각 키, 값 리스트를 만들 수 있다.

 

list(alphabets.keys()) # ['A', 'B', 'C', 'D']

list(alphabets.values()) # [65, 66, 67, 68]

 

키 리스트와 값 리스트를 zip으로 묶으면 다시 원래 dict가 된다.

 

alphabets = {"A": 65, "B": 66, "C": 67, "D": 68}

key_list = list(alphabets.keys())
value_list = list(alphabets.values())

print(dict(zip(key_list, value_list))) # {'A': 65, 'B': 66, 'C': 67, 'D': 68}

 

- items() 메서드를 사용해 (키, 값) 튜플의 리스트를 만들 수 있다.

 

list(alphabets.items()) # [('A', 65), ('B', 66), ('C', 67), ('D', 68)]


# items()는 반복문과 함께 사용하기 편하다.

for letter in alphabets.items():
    print(letter)
    
# 튜플을 언패킹 할 수도 있다.

for key, value in alphabets.items():
    print(f"Key: {key}, Value: {value}")