파이썬에 내장되어 있는 컬렉션 자료형 중 사전에 대해 알아 본다.
사전(dictionaries): 키(keys)와 값(values)으로 이루어진 쌍(pairs)들의 집합
사용 형태: 집합기호 사용
eng_math = {'year': 2017, 'semester' : 2, 'subject': 'Data Science'}
특징
사전은 가변 자료형이다.
사전이름[키이름] = 값
을 이용해 특정 항목의 키에 해당하는 값을 변경할 수 있다.
update()
메소드: 항목 추가
del
함수 또는 pop()
메소드: 특정 항목 삭제items
, keys
, values
등의 메소드를 이용하여 사전의 항목 확인 가능data
디렉토리에 저장된 scores_list.txt
파일은 선수 여덟 명의 점수를 담고 있다.
txt
Name Score
player1 21.09
player2 20.32
player3 21.81
player4 22.97
player5 23.29
player6 22.09
player7 21.20
player8 22.16
목표: 위 파일로부터 1~3등 선수의 이름과 기록을 아래와 같이 확인하기
txt
1등 player5 23.29
2등 player4 22.97
3등 player8 22.16
주의: 이전에는 1~3등의 점수만 확인하였다. 하지만 이제는 선수 이름까지 함께 확인해야 한다.
참조: Head First Programming(한빛미디어) 5장
저장된 파일에서 데이터를 불러와서 한 줄씩 확인하는 방법은 다음과 같다.
In [1]:
result_f = open("data/scores_list.txt")
for line in result_f:
print(line.strip()) # strip 메소드 활용하기
result_f.close()
In [2]:
result_f = open("data/scores_list.txt")
score_list = []
for line in result_f:
(name, score) = line.split()
try:
score_list.append(float(score))
except:
continue
result_f.close()
score_list.sort(reverse=True) # 리스트를 내림차순으로 정렬
print("The top scores were:")
print(score_list[0])
print(score_list[1])
print(score_list[2])
for
반복문을 이용하여 다음과 할 수도 있다.
In [3]:
result_f = open("data/scores_list.txt")
score_list = []
for line in result_f:
(name, score) = line.split()
try:
score_list.append(float(score))
except:
continue
result_f.close()
score_list.sort(reverse=True) # 리스트를 내림차순으로 정렬
print("The top scores were:")
for i in range(3):
print(score_list[i])
이제 위 코드를 수정하여 아래 결과를 얻고자 한다.
txt
1등 player5 23.29
2등 player4 22.97
3등 player8 22.16
즉, 각 등수의 선수 이름까지 필요하다. 어떻게 하면 선수이름과 점수를 동시에 움직이게 할 수 있을까?
마이크로소프트의 엑셀 프로그램을 활용하면 매우 간단하다.
|
|
|
기존 기록표 | 점수 기준으로 정렬하기 | 정렬 후 기록표 |
먼저 앞서 사용한 방식을 약간 수정해서 기록들의 리스트와 선수이름들의 리스트를 생성해보자.
In [4]:
result_f = open("data/scores_list.txt")
score_list = []
name_list = [] # 선수이름 리스트 생성
for line in result_f:
(name, score) = line.split()
try:
score_list.append(float(score))
name_list.append(name) # 선수이름 추가
except:
continue
result_f.close()
In [5]:
print(score_list)
In [6]:
print(name_list)
현재 두 개의 리스트는 기존 테이블의 리스트의 순서와 동일한 순서대로 항목을 갖고 있다.
예를 들어, name_list
리스트의 첫 째 선수의 기록은 score_list
리스트의 첫 째 항목 값이다.
그런데 1~3등의 점수를 얻기 위해 score_list
리스트를 정렬하면 상위 세 명의 점수는 확인할 수 있었지만 어떤 선수가 수상을 해야 할지는 알 수 없었다.
어떻게 해야 할까? name_list
리스트도 정렬할까? 그런데 어떤 기준으로 정렬하나? 이름순으로? 그러면 A
또는 Z
로 시작하는 선수가 항상 1등 아니면 꼴등이 되어 버리는 문제가 발생한다.
이런 문제는 두 개의 리스트를 다룰 때 항상 발생한다. 그리고 일반적으로 두 개의 리스트를 엑셀의 경우처럼 한 가지 기준으로 연동해서 정렬할 수는 없다. 따라서 다른 접근방식이 요구된다.
여기서는 사전 자료형을 이용하여 문제를 해결하고자 한다. 하지만 해결법을 설명하기 전에 사전 자료형을 간단한 예제를 통해 공부하고자 한다.
In [7]:
city_temperature = {}
이제 원하는 자료들의 쌍을 입력한다. 예를 들어 '평택 온도는 22도' 라는 정보를 추가하고자 하면 아래와 같이 하면 된다.
In [8]:
city_temperature['Pyongtaek'] = 22
이제 평택의 정보가 추가되었음을 확인할 수 있다.
In [9]:
city_temperature
Out[9]:
이제 수원과 제주의 정보를 추가하고 확인해보자.
In [10]:
city_temperature['Suwon'] = 18
city_temperature['Jeju'] = 25
city_temperature
Out[10]:
주의: 사전 자료형에서 각 항목의 순서는 전혀 의미가 없다.
In [11]:
city_temperature['Pyongtaek']
Out[11]:
In [12]:
city_temperature['Jeju']
Out[12]:
In [13]:
key_list = city_temperature.keys()
key_list
Out[13]:
주의: 도시명들의 순서 전혀 중요하지 않다.
In [14]:
value_list = city_temperature.values()
value_list
Out[14]:
In [15]:
item_list = city_temperature.items()
item_list
Out[15]:
In [16]:
for key in city_temperature.keys():
print(key,"의 온도는", city_temperature[key], "도 이다.")
사실 keys
메소드를 굳이 사용하지 않아도 된다.
In [17]:
for key in city_temperature:
print(key,"의 온도는", city_temperature[key], "도 이다.")
사전 자료형의 메소드는 그리 많지 않다.
특정 자료형의 메소드를 확인하고자 하면 dir()
함수를 활용한다.
In [18]:
dir(city_temperature)
Out[18]:
주요 메소드들의 활용을 살펴보자.
pop
메소드: 키에 해당하는 항목을 삭제한다.
In [19]:
city_temperature.pop("Suwon")
print(city_temperature)
키가 존재하지 않으면 오류('KeyError')가 발생한다.
In [20]:
city_temperature.pop("Suwon")
print(city_temperature)
특정 키의 존재여부를 확인하려면 keys()
메소드와 in
연산자를 활용한다.
In [21]:
"Suwon" in city_temperature.keys()
Out[21]:
In [22]:
"Jeju" in city_temperature.keys()
Out[22]:
아니면 단순히 in
연산자를 활용할 수도 있다.
In [23]:
"Suwon" in city_temperature
Out[23]:
In [24]:
"Jeju" in city_temperature
Out[24]:
update
메소드: 하나의 사전을 다른 자료형과 합칠 수 있다.
In [25]:
other_city_temperature = {'Ansung': 21, 'Yongin': 23}
city_temperature.update(other_city_temperature)
In [26]:
city_temperature
Out[26]:
get
메소드: 지정한 키(key)에 해당하는 키값(value)를 되돌려 준다.
In [27]:
city_temperature.get('Ansung')
Out[27]:
이제 선수이름과 기록을 연동하여 기록순으로 정렬하는 방법을 다루고자 하며, 이를 위해 사전 자료형을 활용한다.
방식은 앞서 언급한 아래의 코드를 약간 수정하면 된다.
In [28]:
result_f = open("data/scores_list.txt")
score_dict = dict() # 빈 사전 생성
# 아래와 같이 선언해도 된다.
# score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name # 점수와 선수이름의 쌍을 사전에 추가
except:
continue
result_f.close()
print(score_dict)
이제 score_dict
를 기록 기준으로 오름차순으로 정렬하면 된다.
하지만 사전 자료형에는 sort()
메소드가 없다.
대신에 sorted()
함수를 적용할 수 있다.
즉, sorted()
함수를 이용하여 기록을 정렬한 후에 그 순서대로 키값을 읽으면 된다.
In [29]:
sorted(score_dict.keys())
Out[29]:
내림차순으로 정렬하려면 reverse=True
라는 키워드 인자를 추가한다.
In [30]:
for each_record in sorted(score_dict.keys(), reverse=True):
print(score_dict[each_record], each_record)
이제 코드를 정리하면 다음과 같다.
In [31]:
result_f = open("data/scores_list.txt")
score_dict = dict() # 빈 사전 생성
# 아래와 같이 선언해도 된다.
# score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name # 점수와 선수이름의 쌍을 사전에 추가
except:
continue
result_f.close()
score_keys = sorted(score_dict.keys(), reverse=True)
for key in score_keys:
print("Name:", score_dict[key], ", Score:", key)
위 코드를 좀 더 수정하면 등수까지도 보여줄 수 있다.
In [32]:
result_f = open("data/scores_list.txt")
score_dict = dict() # 빈 사전 생성
# 아래와 같이 선언해도 된다.
# score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name # 점수와 선수이름의 쌍을 사전에 추가
except:
continue
result_f.close()
score_keys = sorted(score_dict.keys(), reverse=True)
count = 1
for key in score_keys:
print(str(count)+"등은", score_dict[key], "이고, 점수는", key, "입니다.")
count = count+1
견본답안 1: break
명령문 활용
In [33]:
result_f = open("data/scores_list.txt")
score_dict = dict() # 빈 사전 생성
# 아래와 같이 선언해도 된다.
# score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name # 점수와 선수이름의 쌍을 사전에 추가
except:
continue
result_f.close()
score_keys = sorted(score_dict.keys(), reverse=True)
count = 1
for key in score_keys:
print(str(count)+"등은", score_dict[key], "이고, 점수는", key, "입니다.")
if count < 3:
count = count+1
else:
break
견본답안 2: 아래와 같이 range()
함수를 활용할 수도 있다.
In [34]:
result_f = open("data/scores_list.txt")
score_dict = dict() # 빈 사전 생성
# 아래와 같이 선언해도 된다.
# score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name # 점수와 선수이름의 쌍을 사전에 추가
except:
continue
result_f.close()
score_keys = sorted(score_dict.keys(), reverse=True)
for i in range(3):
key = score_keys[i]
print(str(i+1)+"등은", score_dict[key], "이고, 점수는", key, "입니다.")
견본답안:
In [35]:
result_f = open('data/scores_list.txt')
score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name
except:
continue
result_f.close()
score_keys = sorted(score_dict.keys(), reverse = True)
n_input = float(input('기준이 되는 점수: '))
for key in score_keys:
if key >= n_input:
print(score_dict[key])
견본답안:
In [36]:
# 정렬된 코드 score_keys 가 있다면, `(score_keys[0] - score_keys[-1]` 로 구할 수도 있다.
result_f = open('data/scores_list.txt')
score_dict = {}
for line in result_f:
(name, score) = line.split()
try:
score_dict[float(score)] = name
except:
continue
result_f.close()
scores = score_dict.keys()
max_score = max(scores)
min_score = min(scores)
print('점수 차는', max_score - min_score)