[알고리즘] 카카오 블라인드 2019 - 1. 오픈채팅방 풀이 및 내 코드 리뷰 (JS)
문제를 풀어보고 풀이한 코드, 내가 생각한 주요 포인트, 개선할 점, 더 공부해볼점에 대해서 기록하고자 한다.
이 문제는 제목에도 나와있듯이 카카오 블라인드 2019에 진행되었던 테스트이고
지금은 아래의 링크에서 문제를 확인해볼수 있다.
https://programmers.co.kr/learn/courses/30/lessons/42888
0. 개요
내가 문제를 풀 당시 코드에 신경썼던 부분은 읽을 수 있는 코드와, 상수를 잘 관리해보자였다.
문제에는 채팅방의 기록에 3가지 타입의 동작이 가능하고이에 해당되는 메시지가 있었다.
그래서 이 것을 내가 사용하던 언어인 자바의 Enum 처럼 관리해보려고 하였다.
또한 ES6의 문법을 잘 활용하고자 했다.
그래서 Optional한 Property추가 나 String Interpolation을 가미해보았다.
1. 첫 풀이한 코드
function solution(recordList) {
const Operation = {
Enter: { key: 'Enter', message: '들어왔습니다' },
Leave: { key: 'Leave', message: '나갔습니다' },
Change: { key: 'Change', message: '' },
};
const processedRecordList = recordList.map((record) => {
const divided = record.split(' ');
return {
uid: divided[1],
operation: divided[0],
...(divided[2] && { newNickname: divided[2] }),
};
});
const uidNicknameMap = new Map();
processedRecordList.forEach((record) => {
if (Operation.Leave.key !== record.operation) {
uidNicknameMap.set(record.uid, record.newNickname);
}
});
const result = [];
for (let record of processedRecordList) {
const { uid, operation } = record;
if (Operation.Change.key === operation) {
continue;
}
result.push(
`${uidNicknameMap.get(uid)}님이 ${Operation[operation].message}.`,
);
}
return result;
}
2. 내가 생각한 포인트
1번 문제이니만큼 크게 어려웠던 점은 없는듯하고,
카카오의 해설에 나와있듯이 연관배열(맵)을 사용하면 쉽게 풀 수 있던 문제였다.
나는 내 코드에 포인트를 더 주고 싶었다.
(똑같은 문제를 풀었지만, 채점을 하시는분이 좀 더 봐주셨으면 했다. 지금생각하니깐 좀 쑥쓰럽다.)
그리하여 ES6를 능숙하게 사용하는 것, JS에서 Enum등을 다루는 법을 더 가미해보고자 하였다.
3. 개선할점
변수들을 한군데에 모으고 주석 달기
먼저 눈에 띄는것은 변수들이 함수의 중간중간에 선언이 되어서
어떤 변수가 스코프 내에서 사용되는지 알기가 어려웠다.
그래서 아래와 같이 고쳐보았다.
function solution(recordList) {
// Operation const object 선언
const Operation = {
Enter: { name: 'Enter', message: '들어왔습니다' },
Leave: { name: 'Leave', message: '나갔습니다' },
Change: { name: 'Change', message: null },
};
const uidNicknameMap = new Map(); // uid - nickname을 연관지을 객체
const result = []; // 채팅 결과를 담을 객체
...
// 구현 부분 생략
return result;
}
주석을 통해 간략한 설명을 달고 변수들이 어떤 용도로 쓰이는지 명시해 주었다.
불필요한 로직을 줄이고, 코드 다듬기
recordList
// record를 의미가 담긴 객체 형태로 변환한다
.map((record) => {
const [operation, uid, nickname] = record.split(' ');
// 닉네임이 있다면 uid - nickname 맵에 넣어준다
if (nickname) {
uidNicknameMap.set(uid, nickname);
}
return {
operation: Operation[operation],
uid,
...(nickname && { nickname }),
};
})
첫 번째로는 채팅 기록을 split하여 divided라는 변수에 담아주었는데 이를
ES6의 Array Destructre 구문을 이용해 다듬어 주었다.
또한 newNickname이라는 변수이름을 수정하였다.
처음입장시에는 newNickname보다는 그냥 nickname이 의미상으로 더 맞는듯 했다.
Enter를 처음하는 사람일 수 도 있었기 때문이다!
두 번째로는 forEach를 여러번 사용을 하였는데, 한 번은 없어도 되었다.
map을 통해 객체를 변환하는 과정에서 uid - nickname 연관을 동시에 수행해주었다.
세 번째로는 반환되는 객체에 operation 속성에는 operation 문자열 그대로를 넣었지만,
코드를 다듬을때는 내가 객체화 하였던 상수들을 넣었다.
이제는 newRecord.operation.message를 통해서 메시지에 바로 접근이 가능하다.
그리고 추가적으로 설명을 하자면
...(nickname && { nickname }),
이 구문은 닉네임 변경을 하는 동작에는 nickname 변수가 없다. (undefined)
그래서 닉네임 속성을 추가할 필요가 없었고, 닉네임이 존재할 때만 닉네임 속성을 추가할 수 있게 하였다.
네 번째로는 위쪽 map()과 마지막으로 결과들을 도출해내는 forEach()를 연결해서 작성해주었다.
.forEach(({ uid, operation }) => {
if (operation === Operation.Change) return;
result.push(`${uidNicknameMap.get(uid)}님이 ${operation.message}.`);
});
Object Destructring을 통해서 uid, operation을 즉시 사용할 수 있게 하였다.
또한 Operation.Change는 리턴하게끔하여 continue 되도록 유도하였다.
그 다음에는 벡틱을 사용해서 문자열을 합치는 문법을 사용해 주었다.
최종 수정 코드
function solution(recordList) {
// Operation const object 선언
const Operation = {
Enter: { name: 'Enter', message: '들어왔습니다' },
Leave: { name: 'Leave', message: '나갔습니다' },
Change: { name: 'Change', message: null },
};
const uidNicknameMap = new Map(); // uid - nickname을 연관지을 객체
const result = []; // 채팅 결과를 담을 객체
recordList
// record를 의미가 담긴 객체 형태로 변환한다
.map((record) => {
const [operation, uid, nickname] = record.split(' ');
// 닉네임이 있다면 uid - nickname 맵에 넣어준다
if (nickname) {
uidNicknameMap.set(uid, nickname);
}
return {
operation: Operation[operation],
uid,
...(nickname && { nickname }),
};
})
.forEach(({ uid, operation }) => {
if (operation === Operation.Change) return;
result.push(`${uidNicknameMap.get(uid)}님이 ${operation.message}.`);
});
return result;
}
최종 수정한 코드는 위와 같다. 변수들도 위에 잘 나타나있고, 용도도 설명되었다.
또한 코드를 forEach, for를 혼잡해서 쓰는 것도 없앴고. 한 번 forEach가 낭비되는 것도 줄였다.
더 읽기 좋아진것 같다!! (내가 보기엔!!)
추가적으로 설명이 필요한 것이나, 피드백을 자유롭게 해주시면 감사하겠다!
Author And Source
이 문제에 관하여([알고리즘] 카카오 블라인드 2019 - 1. 오픈채팅방 풀이 및 내 코드 리뷰 (JS)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jon8907/알고리즘-카카오-블라인드-2019-1.-오픈채팅방-JS저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)