딕셔너리(dict)
Last updated
Last updated
딕셔너리
컴퓨터에 있는 폴더를 생각해봅시다. 폴더는 폴더 아이콘, 폴더 이름과 안에 들어있는 내용물로 이루어져 있습니다.
딕셔너리도 이런 폴더와 비슷한 구조로 되어 있습니다. 대신 코딩이기 때문에 아이콘 같은 것은 없고, 폴더 이름과 같은 기능을 하는 key라는 이름과 폴더 안에 들어가 있는 내용물은 value라는 이름을 가지고 있습니다.
이건 제가 관리하고 있는 스터디에 넣은 문제들의 소스 코드를 모아둔 파일인데요. 이게 하나의 딕셔너리라고 볼 수 있습니다.
이 안을 들여다보면 이번주와 저번주에 배운 내용이 모여있습니다.
다양한 출력 방법, 리스트, 문자열, 튜플이 폴더 이름이니까 이게 각각 key 값이라고 생각할 수 있습니다.
다양한 출력 방법이라는 폴더를 클릭해서 들어가 봅시다.
그러면 위와 같이 문제 번호에 대응하는 코드 파일들을 볼 수 있는데요. 이것이 폴더 안의 내용물인 value 값이라고 생각하시면 됩니다.
그래서 아래와 같이 폴더와 딕셔너리를 서로 비교해가면서 이해하시면 편합니다.
폴더
딕셔너리
폴더 이름
key
내용물
value
딕셔너리를 만드는 방법은 중괄호 { }를 사용하거나, dict()를 사용하시면 됩니다.
여기서 특이한 점은 set에서도 중괄호를 사용한다는 것인데요. 조금 전에 배웠던 set에서 t = {}를 사용하지 말라는 이유가 바로 딕셔너리로 선언되기 때문입니다.
key 값과 value 값을 넣어주는 방법은 리스트처럼 처음 선언할 때 넣는 방법인 [1, 2, 3]과 나중에 넣는 방법인 append처럼 방법이 2가지로 나뉩니다.
처음 선언할 때는 'key 값 : value 값' 형태로 넣어주면 됩니다. 콜론(:)의 왼쪽은 key 값, 오른쪽은 value 값입니다.
이렇게 말이죠
이때 key값은 값이 고정된 숫자, 문자열, 튜플을 사용할 수 있습니다. 하지만 value값은 어떤 것이 들어가도 상관없습니다.
나중에 값을 추가하는 방법은 간단합니다. 그냥 dict[key] = value를 입력하면 됩니다.
이렇게 넣어주고 출력을 해보면 아래 사진처럼 나오게 됩니다.
그래서 정리해보면 아래와 같습니다.
이제 기본 내용을 이해했으니 바로 문제를 풀어봅시다.
두 개의 입력 값을 받아서 본문과 같은 출력을 하라고 합니다. 이걸 딕셔너리로 풀어봅시다.
딕셔너리에 넣을 내용은 본문에 있는 내용을 드래그해서 긁어오면 편합니다.
p1은 a와 b의 값이 서로 다를 때 사용할 딕셔너리이고, p2는 a와 b의 값이 서로 같을 때 사용할 딕셔너리 입니다.
이제 for문 안에 a와 b의 값이 같은지 다른지 if / else문을 사용해서 a == b인 경우 출력을 해줍니다.
그리고 문제에서 a와 b중 큰 수부터 부르라고 했으니 이것도 마찬가지로 if / else 문을 통해 출력문을 작성할 수 있습니다. 거기다가 a = 5, b = 6 또는 a = 6, b = 5일 경우 Sheesh Bang이 아닌 Sheesh Beesh를 출력하라고 하였으므로 if / elif / else 문을 통해 나머지를 출력할 수 있게 됩니다.
풀어볼 문제
딕셔너리의 key 값과 value 값을 각각 따로 추출할 수도 있습니다. 혹은 key 값, value 값 전부 다 합쳐서 한 번에 추출할 수도 있습니다.
이런 딕셔너리가 있을 때 key값을 추출하고 싶으면 fruit.keys()를 입력하면 됩니다.
출력이 평소랑 조금 다르게 나옵니다. 이것은 dict_keys라는 자료형이라는 것인데, 일단 이것은 list, tuple로 변환해야 사용할 수 있는 것으로 기억합시다. for문에서는 그냥 사용할 수 있는데 이 내용은 다음 주에 배울 예정입니다.
value값은 key처럼 fruit.values()를 이용하여 추출할 수 있습니다. 이것 역시 dict_values라는 자료형으로 나오므로 list로 변환해야 합니다.
마지막으로 item인데요. item은 (key, value)로 튜플 값이 나오는 dict_items라는 자료형으로 나옵니다.
이 기능들 중에 가장 많이 쓰이는 것은 dict_keys이고, 나머지는 문제를 풀 때 거의 쓰이지 않습니다. values와 items 메소드를 이용해서 풀은 문제는 없던 것으로 기억해요.
그래서 문제들은 전부 key 값을 구하는 문제들밖에 없습니다. key값을 이용한 문제들은 보통 다른 지식과 함께 사용하여 문제를 푸는 편입니다. 그래서 코드 양이 이전보다 많아서 다른 문제들에 비해 좀 어려울 수도 있어요.
문제를 풀어보겠습니다.
모든 소문자 알파벳을 사용해서 문장을 만들었는지 물어보는 문제입니다.
일단 *를 입력받아야 종료를 하고 있으므로 while문이 필요할 것이고, dict를 이용하여 모든 소문자 알파벳이 나타나는 개수를 저장해야 합니다. key 값은 소문자 알파벳, value 값은 0으로 저장을 합시다.
참고로 여기서는 알파벳을 일일이 적는 것보다 아스키 코드를 이용해서 저장하는 것이 편합니다. 알파벳 소문자의 아스키코드는 a = 97부터 z = 122까지 있습니다.
아스키코드는 외울 필요가 없고, 문자를 아스키코드로 출력하는 함수 ord()와 아스키코드를 문자로 출력하는 함수 chr()만 알고 있으면 됩니다. 나중에 쓸 일이 있으면 ord('a'), ord('z'), ord('A'), ord('Z')로 찾으면 되는 것이니까요.
이제 for문을 이용해서 문자열 s를 하나하나 확인해봐야 하는데, D[s[i]] += 1을 하면 코드가 잘 작동할까요?
s[i]의 값이 공백일 때, 1을 더해주면 D에 없는 key값이기 때문에 아래와 같이 오류가 나오게 됩니다.
그러므로 if문과 아스키코드를 이용하여 s[i]가 알파벳 소문자인지 확인하고 개수를 세어 주어야 합니다.
문장 안에 들어있는 알파벳의 개수를 모두 세었으면 이제 dict_keys를 이용하여 모든 알파벳을 사용하였는지 확인해주면 됩니다. 알파벳을 사용하지 않았으면 D[s[i]] += 1을 해주지 않았으니 값이 0이 나오게 됩니다.
다른 문제도 풀어봅시다.
문자열을 줄마다 값을 2개씩 입력받아 현재 회사원들이 회사에 있는지 없는지 확인하여 회사에 남은 회사원의 이름을 출력하라는 문제입니다.
일단 입력값을 받는 코드와 회사원의 상태를 저장할 딕셔너리를 만들어 딕셔너리에 저장해봅시다. key 값은 사원의 이름이고, value 값은 enter나 leave가 되겠네요.
입력을 다 받았으면 회사를 퇴근한 사람은 leave라는 value값을 가질 것이고, 아직 회사에 남아 있다면 enter라는 value 값을 가지고 있다는 것을 알 수 있습니다. 이제 dict_keys를 이용하여 value값이 enter인 회사원들을 리스트에 따로 저장해줍니다.
이제 다 저장을 했으면 출력을 해야 하는데, 사전 순의 역순으로 출력하라고 하였으니 sort안에 reverse인자를 추가하거나, sort만 사용하고 [::-1]을 이용하여 리스트를 뒤집어주면 됩니다. 총 세 가지 방법을 아래에 적어 놨는데 마음에 드는 것을 사용하시면 됩니다.
그리고 출력을 할 때는 for문이나 '\n'.join(ans)를 이용하면 됩니다.
풀어볼 문제