16. 사전과 집합#
두 개의 비순차 자료형 사전과 집합을 소개한다. 비순차 자료형은 문자열, 리스트, 튜플과는 달리 순서를 따지지 않으며 항목의 중복도 허용하지 않는다. 사전은 프로그래밍언어에 따라 연관배열, 맵 등으로 불리기도 하며 매우 다양하게 활용된다. 집합과 사전은 해시 가능한 값만을 이용하기에 해시 가능성도 함께 소개한다. 이후에는 논리식을 이용하여 간편하게 리스트와 정의하는 조건제시법을 다룬다.
16.1. 사전#
사전 자료형은 키key와 값value의
쌍으로 구성된 항목들의 집합이며, 딕셔너리dictionary 라고도 불린다.
예를 들어, 'Hello' 와 'World' 를 키로, '안녕', '세계' 를 각각의 키에 대한 값으로
갖는 사전은 다음과 같다.
{'Hello':'안녕', 'World':'세계'}
빈 사전
빈 사전은 아무것도 포함하지 않는 사전을 의미한다. 빈 사전를 만드는 방법은 아래와 같다.
empty_dict = {}
empty_dict
{}
다음 방식도 가능하다.
empty_dict = dict()
empty_dict
{}
dict() 함수
키-값의 튜플 형식의 항목을 갖는 모음 자료형을 사전으로 변환한다. 단, 키로 사용되는 값은 해시 가능해야 한다.
data = [('Hello', '안녕'), ('World', '세계'), ('Programming', '프로그래밍')]
dict(data)
{'Hello': '안녕', 'World': '세계', 'Programming': '프로그래밍'}
zip() 함수를 활용하면 편리하다.
data = zip('abcde', [1, 2, 3, 4, 5])
data_dict = dict(data)
data_dict
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
사전과 반복문
사전에 대한 반복문은 키key에 대해 실행된다.
for item in data_dict:
print(item, end=' ')
a b c d e
키와 값의 쌍에 대해 반복문을 실행하려면 items() 메서드를 이용한다.
단, 키와 값 각각에 대해 변수를 지정하는 게 좋다.
for key, value in data_dict.items():
print(f"{key:>8} 키의 값: {value}")
a 키의 값: 1
b 키의 값: 2
c 키의 값: 3
d 키의 값: 4
e 키의 값: 5
항목을 쪼개서 사용할 수도 있다.
for item in data_dict.items():
key = item[0]
value = item[1]
print(f"{key:>8} 키의 값: {value}")
a 키의 값: 1
b 키의 값: 2
c 키의 값: 3
d 키의 값: 4
e 키의 값: 5
값에 대해 반복문을 실행하려면 values() 메서드를 이용한다.
for item in data_dict.values():
print(item, end=' ')
1 2 3 4 5
in 연산자
사전의 키로 사용되었는 여부를 알려주는 논리 연산자다.
'city' in {"name": "강현", "age": "3"}
False
in의 부정은 not in을 사용한다. 즉
키로 사용되지 않았는지 여부를 뭍는다.
'city' not in {"name": "강현", "age": "3"}
True
len() 함수
사전에 포함된 항목의 개수를 반환한다.
len({"name": "강현", "age": "3"})
2
16.1.1. 사전 키 인덱싱#
사전에 사용된 키를 이용한 인덱싱이 지원된다.
예를 들어, 아래 딕셔너리 dic에서 'Hello'에 대응하는 값을 확인하고자 하면
다음과 같이 대괄호를 사용하는 인덱싱을 이용한다.
dic = {'Hello' : '안녕', 'World' : '세계'}
dic['Hello']
'안녕'
존재하지 않는 키로 값을 추출하려고 하면, 오류가 발생한다.
dic['Python']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[13], line 1
----> 1 dic['Python']
KeyError: 'Python'
16.1.2. 항목 추가, 업데이트, 삭제#
아래와 같은 형식으로 사전에 항목을 추가하거나 업데이트 한다.
사전[key] = value
예를 들어, dic에 Python : 파이썬 항목을 다음과 같이 추가할 수 있다.
dic['Python'] = '파이썬'
dic
{'Hello': '안녕', 'World': '세계', 'Python': '파이썬'}
이미 사용된 키를 이용하면 키와 연결된 값이 업데이트 된다.
dic['World'] = '세상'
dic
{'Hello': '안녕', 'World': '세상', 'Python': '파이썬'}
사전의 항목은 del 명령어에 키를 지정하여 삭제한다.
del dic['World']
dic
{'Hello': '안녕', 'Python': '파이썬'}
16.1.3. 사전 메서드#
사전 자료형이 제공하는 주요 메서드는 아래와 같다.
기능 |
메서드 |
설명 |
|---|---|---|
키 확인 |
|
사전에 사용된 키로 구성된 순차 자료형 값 반환 |
값 확인 |
|
사전에 사용된 값으로 구성된 순차 자료형 값 반환 |
키와 값 확인 |
|
사전에 사용된 키와 값의 순서쌍으로 구성된 순차 자료형 값 반환 |
값 반환 |
|
지정된 키에 대한 값 반환 |
dic = {'Hello' : '안녕', 'World' : '세계'}
keys() 메서드: 키로 이루어진 모음 자료형 반환
dic.keys()
dict_keys(['Hello', 'World'])
values() 메서드: 값으로 이루어진 모음 자료형 반환
dic.values()
dict_values(['안녕', '세계'])
items() 메서드: (키, 값) 모양의 쌍으로 이루어진 모음 자료형 반환
dic.items()
dict_items([('Hello', '안녕'), ('World', '세계')])
get() 메서드: 지정된 키와 연관된 값 반환
dic.get('Hello')
'안녕'
존재하지 않는 키를 사용하면 기본값으로 None이 사용된다.
dic.get('hello')
키가 사용되지 않았을 때 기본값을 바꾸려면 둘째 인자를 지정한다.
dic.get('hello', "해당 키가 없어요.")
'해당 키가 없어요.'
예제
6명 정보를 이용하여 키는 이름, 값은 해당 이름의 정보를 담은 리스트를 사용하는 사전을
가리키는 info_dict 변수를 선언하라.
info_list = [['김강현', '010-1234-5678', 20, 172.5, '제주'],
['황현', '02-9871-1234', 19, 163.5, '서울'],
['남궁수현', '01-3456-7891', 21, 156.7, '경기'],
['최흥선', '070-4321-1111', 21, 187.2, '부산'],
['김선주', '010-3333-8888', 22, 164.6, '광주'],
['함중아', '010-7654-2345', 18, 178.3, '강원']]
답:
6명 각자의 이름을 키로, 나머지 정보로 구성된 리스트를 값으로 사용하는 사전을 구성한다.
이를 위해 for 반복문과 15.4절의 리스트 해체를 이용한다.
먼저 info_list의 항목은 아래 형식임에 주의한다.
person = ['김강현', '010-1234-5678', 20, 172.5, '제주']
위 리스트를 이름과 나머지로 구분하기 위해 다음과 같이 리스트 해체를 이용한다.
name, *rest = person
그러면 name은 이름을, rest는 나머지 항목으로 구성된 리스트를 가리키게 되어
두 변수를 다음과 같이 선언한 것과 동일하다.
name = person[0]
rest = person[1:]
위 설명을 정리해서 info_dict 변수를 아래와 같이 선언한다.
info_dict = dict()
for person in info_list:
name, *rest = person
info_dict[name] = rest
info_dict
{'김강현': ['010-1234-5678', 20, 172.5, '제주'],
'황현': ['02-9871-1234', 19, 163.5, '서울'],
'남궁수현': ['01-3456-7891', 21, 156.7, '경기'],
'최흥선': ['070-4321-1111', 21, 187.2, '부산'],
'김선주': ['010-3333-8888', 22, 164.6, '광주'],
'함중아': ['010-7654-2345', 18, 178.3, '강원']}
예를 들어 김선주의 정보를 보고 싶으면 다음과 같이 실행한다.
info_dict['김선주']
['010-3333-8888', 22, 164.6, '광주']
예제
이름을 물으면 나이를 확인해주는 name_age() 함수를 선언하라.
단, 이름이 없으면 “정보 없음”을 반환해야 한다.
힌트: get() 사전 메서드 활용
답:
앞서 선언한 info_dict 변수를 활용할 수 있다.
이유는 이름을 사용하여 인덱싱을 적용하면 전화번호, 나이, 키, 출생지 정보로 구성된 리스트가 확인된다.
따라서 인덱싱으로 쉽게 나이를 확인할 수 있다.
그런데 키 인덱싱을 활용할 때 키가 사용되지 않았다면 오류가 발생한다.
따라서 try-except 명령문을 이용하여 다음과 같이 name_age() 함수를 구현할 수 있다.
def name_age(name):
try:
info = info_dict[name]
return info[1]
except KeyError:
return "정보없음"
반면에 get() 메서드를 활용하면 오류 없이 코드가 실행된다.
다면 반환값이 None인지 여부를 구분해야 한다.
def name_age(name):
info = info_dict.get(name)
# info가 None이 아닌지 여부 판단
if info:
return info[1]
else:
return "정보없음"
16.2. 집합#
집합 자료형은 수학에서 다루는 집합처럼 작동하도록 만든 비순차 모음 자료형이며 다음과 같이 중괄호를 사용하여 정의된다. 집합은 항목의 중복을 허용하지 않고, 항목들 사이의 순서 또한 무시된다. 따라서 인덱싱이나 슬라이싱을 지원하지 않는다.
{항목1, 항목2, 항목3, ..., 항목n}
a_set = {4, 4, 9.2, "apple", True, 4}
a_set
{4, 9.2, True, 'apple'}
공집합
공집합empty set은 아무것도 포함하지 않는 집합을 의미한다. 공집합를 만드는 방법은 아래와 같다.
empty_set = set()
empty_set
set()
{}은 빈 사전을 가리킴에 주의한다.
a = {}
type(a)
dict
set() 함수
임의의 모음 자료형을 집합으로 변환한다. 이 과정에서 순서와 중복이 무시된다.
set([5, 1, 1, 2, 5, 5, 1])
{1, 2, 5}
set((1, 3, 3, 9, 1))
{1, 3, 9}
순차 자료형의 항목에서 중복을 제거하고 싶을 때 set() 함수가 유용하게 활용된다.
예를 들어 아래 코드는 리스트에서 중복된 항목이 삭제된,
하지만 동일한 항목을 포함한 새로운 리스트를 생성한다.
단, 기존 리스트에서 사용된 항목들의 순서는 보존되지 않음에 주의한다.
list(set([5, 1, 1, 2, 5, 5, 1]))
[1, 2, 5]
in 연산자
집합의 항목(원소)으로 등장하는지 여부를 알려주는 논리 연산자다.
1 in {1, 2, 3, 9, 4}
True
'a' not in {1, 'b', True, 9}
True
len() 함수
집합에 포함된 항목의 개수를 반환한다.
len({1, 3, 5, 7, 9})
5
16.2.1. 집합 메서드#
집합 자료형이 제공하는 주요 메서드는 아래와 같다.
기능 |
메서드 |
설명 |
|---|---|---|
합집합 |
|
|
교집합 |
|
|
차집합 |
|
|
부분집합 여부 |
|
|
항목 추가 |
|
|
학목 삭제 |
|
|
여기서는 집합 메서드를 자세히 다루지 않는다. 이유는 각각의 메서드의 기능이 중, 고등학교에서 배운 집합 연산과 동일하기 때문이다.
합집합 생성
A = {1, 2, 3}
B = {2, 4}
A.union(B)
{1, 2, 3, 4}
교집합 생성
A.intersection(B)
{2}
차집합 생성
A.difference(B)
{1, 3}
부분집합 여부 확인
A.issubset(B)
False
A.issubset(A.union(B))
True
항목(원소) 추가
A.add(5)
A
{1, 2, 3, 5}
항목(원소) 삭제
A.remove(5)
A
{1, 2, 3}
여기서는 아래 예제를 이용하여 중복을 없애는 set() 함수의 유용성을 소개한다.
예제
info_dict를 이용하여 키는 나이, 값은 해당 나이를 갖는 사람의 수를 사용하는 사전을 가리키는
age_count_dict를 선언하라.
답:
info_dict는 다음과 같다.
info_dict
{'김강현': ['010-1234-5678', 20, 172.5, '제주'],
'황현': ['02-9871-1234', 19, 163.5, '서울'],
'남궁수현': ['01-3456-7891', 21, 156.7, '경기'],
'최흥선': ['070-4321-1111', 21, 187.2, '부산'],
'김선주': ['010-3333-8888', 22, 164.6, '광주'],
'함중아': ['010-7654-2345', 18, 178.3, '강원']}
먼저 나이로 구성된 리스트를 생성한다.
ages = []
for person in info_list:
ages.append(person[2])
print(ages)
[20, 19, 21, 21, 22, 18]
리스트에 포함된 나이를 확인하기 위해 중복을 제거한다. 이를 위해 집합 자료형으로 변환시킨다.
ages_set = set(ages)
ages_set
{18, 19, 20, 21, 22}
ages_set 집합에 포함된 각각의 항목을 대상으로 count() 리스트 메서드를 적용하면 원하는
사전을 생성할 수 있다.
age_count_dict = dict()
for age in ages_set:
age_count_dict[age] = ages.count(age)
age_count_dict
{18: 1, 19: 1, 20: 1, 21: 2, 22: 1}
16.2.2. 해시 가능성#
집합의 항목으로 리스트, 사전, 집합과 같은 가변 자료형은 사용할 수 없다.
{[1, 3], 4}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[58], line 1
----> 1 {[1, 3], 4}
TypeError: unhashable type: 'list'
사전의 키 또한 리스트를 키로 사용할 수 없다.
no_list_keys = {[1, 2]: "리스트는 키로 사용할 수 없음"}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[59], line 1
----> 1 no_list_keys = {[1, 2]: "리스트는 키로 사용할 수 없음"}
TypeError: unhashable type: 'list'
이유는 리스트 등의 가변 자료형은 해시 가능하지 않기 때문이다.
hash() 함수
파이썬 객체의 해시 가능성은 hash() 함수의 인자로 사용될 수 있는가에 의해 결정된다.
즉 hash() 함수와 함께 호출됐을 때 오류가 발생하지 않아야 한다.
이렇게 hash() 함수와 함께 호출되었을 때 오류가 발생하지 않은 값을
해시 가능hashable하다고 부른다.
해시 가능한 값에 대해 hash() 함수의 반환값은 특정 정수이며
서로 다른 두 값은 서로 다른 반환값을 갖는다.
즉, 조금이라도 다른 해시 가능한 값이 인자로 지정되면 다른 값을 계산한다.
hash('123')
-6307178578295685641
hash('123 ')
3543337771683958828
hash((1, 3, 4))
-1070212610609621906
hash((1, 2, 4))
-4363729961677198915
해시 함수의 반환값
hash() 함수의 반환값이 실행할 때마다 달라질 수 있다.
이는 보안상의 이유로 무작위 기능이 적용되기 때문이다.
항상 고정된 값을 반환하는 해시 함수도 있지만 여기서는 다루지 않는다.
반면에 리스트 등 가변 자료형의 객체는 해시 가능하지 않다.
hash([1, 3])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[64], line 1
----> 1 hash([1, 3])
TypeError: unhashable type: 'list'
리스트를 포함한 튜플도 해시 가능하지 않다.
hash(([1, 2], 3))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[65], line 1
----> 1 hash(([1, 2], 3))
TypeError: unhashable type: 'list'
집합에 해시 가능한 값만 포함될 수 있는 이유는 두 항목을 구별하기 위해 hash() 함수를 이용하기 때문이다.
반면에 리스트 등과 같은 가변 자료형의 값은 언제든 변할 수 있기에 정체를
제대로 파악할 수 없다.
16.3. 조건제시법#
조건제시법comprehension을 이용하여 리스트, 집합, 사전을 정의할 수 있다.
리스트 조건제시법
수학에서 0과 10사이에 있는 홀수들의 제곱을 원소로 갖는 집합을 조건제시법으로 표현하면 다음과 같다.
0과 10 사이에 있는 홀수들의 제곱을 항목으로 갖는 리스트를 for 반복문으로 구현해 보자.
zero2ten_odd = []
for x in range(11):
if x%2 == 1:
zero2ten_odd.append(x**2)
zero2ten_odd
[1, 9, 25, 49, 81]
조건제시법을 이용하여 보다 간단하게 리스트를 생성할 수 있다.
zero2ten_odd = [x**2 for x in range(11) if x%2 == 1]
zero2ten_odd
[1, 9, 25, 49, 81]
위 두 코드를 비교하면 조건제시법의 작동원리를 이해할 수 있을 것이다.
집합 조건제시법
위 결과를 집합으로 구현하면 다음과 같다.
zero2ten_odd_set = {x**2 for x in range(11) if x%2 == 1}
zero2ten_odd_set
{1, 9, 25, 49, 81}
사전 조건제시법
조건제시법을 이용하여 사전을 생성하는 과정도 유사하다. 아래 코드는 0부터 10 사이의 홀수를 키로, 홀수의 제곱은 값으로 갖는 항목으로 구성된 사전을 생성한다.
odd_squares = {x : x**2 for x in range(11) if x%2 == 1}
odd_squares
{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
반면에 아래 코드는 문장에 포함된 단어를 키로, 단어의 길이를 값으로 갖는 항목들로 구성된 사전을 생성한다.
words = '파이썬은 범용 프로그래밍 언어입니다.'.split()
print(words)
['파이썬은', '범용', '프로그래밍', '언어입니다.']
len_dict = {k : len(k) for k in words}
len_dict
{'파이썬은': 4, '범용': 2, '프로그래밍': 5, '언어입니다.': 6}
16.4. 예제#
예제 1
아래 코드 중 오류가 발생하는 코드를 예측하여 말하고, 코드를 실행시켜 확인하여라.
(1)
dic1 = { 1 : 'a'}
dic1
{1: 'a'}
답:
사전의 키는 해시 가능해야 하는데, 정수는 해시 가능하다.
hash(1)
1
(2)
dic3 = {'abc' : 'a'}
dic3
{'abc': 'a'}
답:
사전의 키는 해시 가능해야 하는데, 문자열 해시 가능하다.
hash('abc')
-2898649570265123009
(3)
dic4 = {[1, 2] : 'a'}
dic4
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[5], line 1
----> 1 dic4 = {[1, 2] : 'a'}
2 dic4
TypeError: unhashable type: 'list'
답:
사전의 키는 해시 가능해야 하는데, 리스트는 해시 가능하지 않다.
hash([1, 2])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 hash([1, 2])
TypeError: unhashable type: 'list'
예제 2
영어 단어는 키로, 단어의 뜻은 값으로 하는 사전이 다음과 같이 주어졌다.
eng_dict = {'dog': '개', 'cat': '고양이', 'lion': '사자', 'tiger': '호랑이', 'snake': '뱀'}
영어 단어가 인자로 입력되었을 때 사전의 키로 사용되었다면 뜻을 반환하고,
아니면 아래 문장을 반환하는 eng_fun() 함수를 선언하라.
단, 대소문자는 구분하지 않는다.
찾는 단어가 없습니다.
답:
사전에 키로 사용된 영어 단어는 모두 소문자만 사용한다. 따라서 입력값을 먼저 소문자만 사용하도록 한 다음에 키로 사용되었는지 여부를 판단한다.
def eng_fun(word):
word = word.lower()
if word in eng_dict:
return eng_dict[word]
else:
return '찾는 단어가 없습니다.'
eng_fun('dog')
'개'
eng_fun('fox')
'찾는 단어가 없습니다.'
다음과 같이 사전의 get() 메서드를 이용하여 eng_func() 함수를 선언할 수도 있다.
def eng_fun(word):
word = word.lower()
return eng_dict.get(word, '찾는 단어가 없어요.')
eng_fun('dog')
'개'
eng_fun('fox')
'찾는 단어가 없어요.'
반면에 다음과 같이 사전 인덱싱을 이용하면 찾는 단어가 없는 경우 오류가 발생한다.
def eng_fun(word):
word = word.lower()
return eng_dict[word]
eng_fun('dog')
'개'
eng_fun('fox')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[16], line 1
----> 1 eng_fun('fox')
Cell In[14], line 3, in eng_fun(word)
1 def eng_fun(word):
2 word = word.lower()
----> 3 return eng_dict[word]
KeyError: 'fox'
다음과 같이 예외처리를 이용할 수는 있다.
def eng_fun(word):
word = word.lower()
try:
return eng_dict[word]
except:
return "찾는 단어가 없어요."
eng_fun('dog')
'개'
eng_fun('fox')
'찾는 단어가 없어요.'
하지만 예외처리를 하는 것보다는 get() 메서드를 사용하여 애초에 오류가 발생하지 않도록
코드를 작성하는 게 보다 중요하다.
예제 3
정수들의 리스트가 인자로 입력되었을 때 리스트의 항목은 키로,
해당 항목이 위치한 곳의 인덱스들의 리스트를 값으로 갖는 사전 객체를 반환하는
list2dic() 함수를 구현하라.
list2dic() 함수는 예를 들어 아래와 같이 작동해야 한다.
list2dic([2, 5, 2, 3, 3, 2]) = {2: [0, 2, 5], 3: [3, 4], 5: [1]}
list2dic([15, 3, 15, 1, 3, 8]) = {1: [3], 3: [1, 4], 8: [5], 15: [0, 2]}
힌트: enumerate() 함수, 리스트의 count() 메서드,
collections 모듈의 defaultdict 클래스를 이용한다.
답 1:
def list2dic(xs):
list_dict = dict()
for i, item in enumerate(xs):
if item in list_dict:
list_dict[item].append(i)
else:
list_dict[item] = [i]
return list_dict
print(list2dic([2, 5, 2, 3, 3, 2]))
print(list2dic([15, 3, 15, 1, 3, 8]))
{2: [0, 2, 5], 5: [1], 3: [3, 4]}
{15: [0, 2], 3: [1, 4], 1: [3], 8: [5]}
답 2:
collections 모듈의 defaulitdict를 활용하면 보다 간단하게 함수를 구현할 수 있다.
from collections import defaultdict
list_dict = defaultdict(list)
list_dict
defaultdict(list, {})
list_dict[1].append(3)
list_dict[2].append(0)
list_dict
defaultdict(list, {1: [3], 2: [0]})
def list2dic(xs):
list_dict = defaultdict(list)
for i, item in enumerate(xs):
list_dict[item].append(i)
return dict(list_dict)
print(list2dic([2, 5, 2, 3, 3, 2]))
print(list2dic([15, 3, 15, 1, 3, 8]))
{2: [0, 2, 5], 5: [1], 3: [3, 4]}
{15: [0, 2], 3: [1, 4], 1: [3], 8: [5]}
예제 4
(1) 아래 리스트를 리스트 조건제시법으로 정의하라.
[3, 6, 9, 12, 15]
답:
multiples_3 = [ 3*x for x in range(1,6) ]
print(multiples_3)
[3, 6, 9, 12, 15]
또는
multiples_3 = [ x for x in range(1,16) if x % 3 == 0]
print(multiples_3)
[3, 6, 9, 12, 15]
(2) 0부터 20까지의 자연수 중에서 3으로 나눈 나머지가 2이면서 짝수인 수의 제곱으로 이루어진 리스트를 조건제시법으로 정의하라. 즉, 아래 리스트를 조건제시법으로 생성해야 한다.
[4, 64, 196, 400]
답:
list_modulo3 = [x**2 for x in range(0, 21) if x%3 == 2 and x%2 == 0]
print(list_modulo3)
[4, 64, 196, 400]
예제 5
6명의 정보가 다음과 같다.
kgh = ['김강현', '010-1234-5678', 20, 172.3, '제주']
whang = ['황현', '02-9871-1234', 19, 163.5, '서울']
namgung = ['남세원', '010-3456-7891', 21, 156.7, '경기']
choihs = ['최흥선', '070-4321-1111', 21, 187.2, '부산']
sjkim = ['김현선', '010-3333-8888', 22, 164.6, '광주']
ja = ['함중아', '010-7654-2345', 18, 178.3, '강원']
info_list = [kgh, whang, namgung, choihs, sjkim, ja]
info_list
[['김강현', '010-1234-5678', 20, 172.3, '제주'],
['황현', '02-9871-1234', 19, 163.5, '서울'],
['남세원', '010-3456-7891', 21, 156.7, '경기'],
['최흥선', '070-4321-1111', 21, 187.2, '부산'],
['김현선', '010-3333-8888', 22, 164.6, '광주'],
['함중아', '010-7654-2345', 18, 178.3, '강원']]
(1) info_list에 포함된 6명의 이름과 전화번호만으로 구성된 사전을 가리키는 phone_dict 변수를
for 반복문을 이용하여 선언하라.
단, 키는 이름, 값은 전화번호로 지정하며, 조건제시법은 사용하지 않는다.
답:
phone_dict = dict()
for people in info_list:
name = people[0]
phone_number = people[1]
phone_dict[name] = phone_number
phone_dict
{'김강현': '010-1234-5678',
'황현': '02-9871-1234',
'남세원': '010-3456-7891',
'최흥선': '070-4321-1111',
'김현선': '010-3333-8888',
'함중아': '010-7654-2345'}
(2) phone_dict 변수가 가리키는 값을 조건제시법을 이용하여 선언하라.
답:
phone_dict = {people[0]:people[1] for people in info_list}
phone_dict
{'김강현': '010-1234-5678',
'황현': '02-9871-1234',
'남세원': '010-3456-7891',
'최흥선': '070-4321-1111',
'김현선': '010-3333-8888',
'함중아': '010-7654-2345'}
(3) phone_dict를 이용해서 이름을 지정하면 전화번호를 알려주는 phone_book() 함수를 정의하라.
def phone_book(name):
return phone_dict[name]
phone_book('김현선')
'010-3333-8888'
phone_book('최흥선')
'070-4321-1111'
예제 6
아래 문자열을 이용한다.
lyrics = "Twinkle, twinkle, little star. How I wonder what you are."
(1) 위 문자열을 소문자로 변경한 후, 공백을 기준으로 쪼개진 단어들의 리스트를 lyrics_list 변수에 할당하라.
lyrics_list = lyrics.lower().split()
lyrics_list
['twinkle,',
'twinkle,',
'little',
'star.',
'how',
'i',
'wonder',
'what',
'you',
'are.']
(2) lyrics_list의 각 항목의 문자열 길이를 항목으로 갖는 리스트를 만들어라.
예를 들어, ['hello', 'python']의 경우, 각 항목의 문자열 길이를 항목으로 갖는 리스트는 [5, 6] 이다.
[len(x) for x in lyrics_list]
[8, 8, 6, 5, 3, 1, 6, 4, 3, 4]
(3) lyrics_list의 항목 중 일부는 콤마(,)나 마침표(.)가 사용되었다. 콤마나 마침표를 제외한 단어의 길이를 표시하도록 (2)의 코드를 수정하여라.
[len(x.strip('.').strip(',')) for x in lyrics_list]
[7, 7, 6, 4, 3, 1, 6, 4, 3, 3]
예제 7
리스트를 인자로 받아서 사용된 항목의 개수를 반환하는 함수
count_elem()를 구현하라.
단, 중복 항목은 하나로 간주한다.
count_elem([2, 5, 2, 3, 3, 8, 2, 7]) = 5
count_elem([15, 3, 15, 1, 3]) = 3
답:
def count_elem(xs):
return len(set(xs))
print(count_elem([2, 5, 2, 3, 3, 8, 2, 7]))
print(count_elem([15, 3, 15, 1, 3]))
5
3
예제 8
교육 참가자 명단과 수료자 명단이 아래처럼 리스트로 주어다.
participant = ['Apeach', 'Ryan', 'Muzi', 'Choonsik', 'Neo', 'Tube']
completion = ['Ryan', 'Muzi', 'Neo', 'Choonsik']
수료하지 못한 사람들의 명단을 리스트로 출력하는 코드를 작성하여라. 단, 참여자 중 동명이인은 없고, 순서는 중요하지 않다.
답:
unfinished = list(set(participant) - set(completion))
unfinished
['Apeach', 'Tube']
또는
unfinished = list(set(participant).difference(set(completion)))
unfinished
['Apeach', 'Tube']
16.5. 연습문제#
참고: (연습) 사전과 집합