(프로그래머스 Lv.2) 오픈채팅방 / with.딕셔너리
문제링크: https://school.programmers.co.kr/learn/courses/30/lessons/42888
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def solution(record):
user_dict = {}
log = []
for entry in record:
data = entry.split()
command, uid = data[0], data[1]
if command == "Enter":
nickname = data[2]
user_dict[uid] = nickname
log.append([uid, "님이 들어왔습니다."])
elif command == "Leave":
log.append([uid, "님이 나갔습니다."])
elif command == "Change":
nickname = data[2]
user_dict[uid] = nickname
return [user_dict[uid] + action for uid, action in log]
풀이
- uid별 nickname을 저장하기 위한 딕셔너리 생성.
- 왜 딕셔너리로 선언을 해야될까?
- 딕셔너리형은 key:value값을 가진다.
- 즉 이 문제에서 key는 uid, value는 nickname으로 설정하면,
- nickname을 change할 때 (nickname에 새로운 값을 넣어야 될 때) O(1) 의 시간이 걸린다.
- 왜냐면 key값만 비교하면 되기 때문이다.
- 근데 만약 uid와 nickname을
[[uid, nickname]]
형태의 이중리스트로 저장했다면,- nickname을 change해야 될 때,
- 위에서 선언한 이중리스트 길이만큼 반복문을 돌아서,
- 만약 현재 uid와 이중리스트에 있는 uid값이 같다면,
- 해당 번째의 리스트 값을 새로운 값으로 변경해줬을 것이다.
- 근데 이렇게 하면 이중리스트에 있는 모든 uid값을 현재 uid값과 비교해야 되기 때문에, O(n) 의 시간이 걸린다.
- 따라서 uid와 nickname을 담을 자료는 딕셔너리형으로 선언한다.
- 왜 딕셔너리로 선언을 해야될까?
- “a님이 들어왔습니다.” or “a님이 나갔습니다.”를 출력하기 위한 log는 리스트로 선언한다.
- 이 때 리스트를 사용한 이유는, 모든 유저의 log(입장, 퇴장)를 출력해주기 위해서다.
- record는 문자열 리스트 형태로
["command uid nickname"]
와 같이 공백을 기준으로 선언된다.- 따라서 record의 현재 요소를 빼내기 위해 record만큼 반복문을 돌아서,
- data 변수에 record의 현재 요소를 split()하여 저장하고,
- command에 현재 어떤 command(Enter, Leave, Change 中…)를 사용했는지 저장하고,
- uid엔 현재 어떤 uid를 갖고 있는지 저장한다. cf. 이 때, nickname은 저장하지 않는 이유는 command가 Leave일 경우 nickname이 없고 uid만 있기 때문이다. 따라서 만약 nickname도 바로 저장한다면, list index out of range 오류가 발생한다.
- 이제는 3-1 반복문 안에서 command별 조건에 맞게 if문을 짜면 된다.
- 만약 command가 Enter면,
- data[2]를 nickname에 저장하고,
- user_dict[uid]에다 위에서 저장한 값을 넣은 다음, (당연하겠지만, 그냥 바로 data[2]를 넣어줘도 되긴한다.)
- 이중리스트 형태로 log에 uid와 “님이 들어왔습니다.” 를 저장한다.
- log를 이중리스트 형태로 저장한다.
- 만약 command가 Leave면,
- log에 이중리스트 형태로 uid와 “님이 나갔습니다.” 를 저장한다. - 1, 2번 공통 참고사항: 이중리스트 형태로 log에 uid와 action(들어왔는지, 나갔는지)을 저장하는 이유는 채팅방을 나갔다가 닉네임을 변경해서 다시 들어왔을 때 변경한nickname 값을 얻기 위해서다.
- 만약 command가 change면,
- 현재 uid의 nickname을 현재 nickname값으로 변경한다.
- 만약 command가 Enter면,
- 그 후엔, log를 반복문을 돌려서 uid와 action(“들어왔습니다” or “나갔습니다”)을가져온다.
- 그러고 빈 리스트인 result에 uid에 맞는 nickname과 action을 추가한다.
- 그 후 result를 return하면 된다~..
결론
회원별로 고유한 id가 있을 땐 딕셔너리형을 사용하자.
참고
1
2
3
4
5
6
# return 할 때 사용한 컴프리헨션을 풀어쓰면 아래와 같다.
# result = []
# for uid, action in log:
# message = user_dict[uid] + action
# result.append(message)
# return result
#딕셔너리 #2019_kakao_blind_recruitment #리스트요소_공백으로_구분하기
This post is licensed under CC BY 4.0 by the author.