Post

(프로그래머스 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]

풀이

  1. uid별 nickname을 저장하기 위한 딕셔너리 생성.
    1. 딕셔너리로 선언을 해야될까?
      1. 딕셔너리형은 key:value값을 가진다.
      2. 즉 이 문제에서 key는 uid, value는 nickname으로 설정하면,
      3. nickname을 change할 때 (nickname에 새로운 값을 넣어야 될 때) O(1) 의 시간이 걸린다.
      4. 왜냐면 key값만 비교하면 되기 때문이다.
    2. 근데 만약 uid와 nickname을 [[uid, nickname]] 형태의 이중리스트로 저장했다면,
      1. nickname을 change해야 될 때,
      2. 위에서 선언한 이중리스트 길이만큼 반복문을 돌아서,
      3. 만약 현재 uid와 이중리스트에 있는 uid값이 같다면,
      4. 해당 번째의 리스트 값을 새로운 값으로 변경해줬을 것이다.
      5. 근데 이렇게 하면 이중리스트에 있는 모든 uid값을 현재 uid값과 비교해야 되기 때문에, O(n) 의 시간이 걸린다.
    3. 따라서 uid와 nickname을 담을 자료는 딕셔너리형으로 선언한다.
  2. “a님이 들어왔습니다.” or “a님이 나갔습니다.”를 출력하기 위한 log는 리스트로 선언한다.
    1. 이 때 리스트를 사용한 이유는, 모든 유저의 log(입장, 퇴장)를 출력해주기 위해서다.
  3. record는 문자열 리스트 형태로 ["command uid nickname"] 와 같이 공백을 기준으로 선언된다.
    1. 따라서 record의 현재 요소를 빼내기 위해 record만큼 반복문을 돌아서,
    2. data 변수에 record의 현재 요소를 split()하여 저장하고,
    3. command에 현재 어떤 command(Enter, Leave, Change 中…)를 사용했는지 저장하고,
    4. uid엔 현재 어떤 uid를 갖고 있는지 저장한다. cf. 이 때, nickname은 저장하지 않는 이유는 command가 Leave일 경우 nickname이 없고 uid만 있기 때문이다. 따라서 만약 nickname도 바로 저장한다면, list index out of range 오류가 발생한다.
  4. 이제는 3-1 반복문 안에서 command별 조건에 맞게 if문을 짜면 된다.
    1. 만약 command가 Enter면,
      1. data[2]를 nickname에 저장하고,
      2. user_dict[uid]에다 위에서 저장한 값을 넣은 다음, (당연하겠지만, 그냥 바로 data[2]를 넣어줘도 되긴한다.)
      3. 이중리스트 형태로 log에 uid와 “님이 들어왔습니다.” 를 저장한다.
      4. log를 이중리스트 형태로 저장한다.
    2. 만약 command가 Leave면,
      1. log에 이중리스트 형태로 uid와 “님이 나갔습니다.” 를 저장한다. - 1, 2번 공통 참고사항: 이중리스트 형태로 log에 uid와 action(들어왔는지, 나갔는지)을 저장하는 이유는 채팅방을 나갔다가 닉네임을 변경해서 다시 들어왔을 때 변경한nickname 값을 얻기 위해서다.
    3. 만약 command가 change면,
      1. 현재 uid의 nickname을 현재 nickname값으로 변경한다.
  5. 그 후엔, log를 반복문을 돌려서 uid와 action(“들어왔습니다” or “나갔습니다”)을가져온다.
  6. 그러고 빈 리스트인 result에 uid에 맞는 nickname과 action을 추가한다.
  7. 그 후 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 #리스트요소_공백으로_구분하기

[image](https://i.pinimg.com/736x/83/66/f3/8366f342b91e5f0524d3e13fb52bd206.jpg)

This post is licensed under CC BY 4.0 by the author.