안녕하세요
우테코 프리코스 1주차 - 문제 6 (리팩토링O) 본문
https://github.com/youngentry/javascript-onboarding/blob/youngentry/docs/PROBLEM6.md
🚀 기능 요구 사항
우아한테크코스에서는 교육생(이하 크루) 간 소통 시 닉네임을 사용한다. 간혹 비슷한 닉네임을 정하는 경우가 있는데, 이러할 경우 소통할 때 혼란을 불러일으킬 수 있다.
혼란을 막기 위해 크루들의 닉네임 중 같은 글자가 연속적으로 포함 될 경우 해당 닉네임 사용을 제한하려 한다. 이를 위해 같은 글자가 연속적으로 포함되는 닉네임을 신청한 크루들에게 알려주는 시스템을 만들려고 한다.
신청받은 닉네임 중 같은 글자가 연속적으로 포함 되는 닉네임을 작성한 지원자의 이메일 목록을 return 하도록 solution 메서드를 완성하라.
제한사항
- 두 글자 이상의 문자가 연속적으로 순서에 맞추어 포함되어 있는 경우 중복으로 간주한다.
- 크루는 1명 이상 10,000명 이하이다.
- 이메일은 이메일 형식에 부합하며, 전체 길이는 11자 이상 20자 미만이다.
- 신청할 수 있는 이메일은 email.com 도메인으로만 제한한다.
- 닉네임은 한글만 가능하고 전체 길이는 1자 이상 20자 미만이다.
- result는 이메일에 해당하는 부분의 문자열을 오름차순으로 정렬하고 중복은 제거한다.
실행 결과 예시
formsresult
[ ["jm@email.com", "제이엠"], ["jason@email.com", "제이슨"], ["woniee@email.com", "워니"], ["mj@email.com", "엠제이"], ["nowm@email.com", "이제엠"] ] | ["jason@email.com", "jm@email.com", "mj@email.com"] |
✔구현 기능 목록 리스트
- 1단계) 모든 연속되는 패턴을 찾아 Set 집함에 담아 중복을 없앱니다.
- 2단계) [pattern, 0] 배열을 생성하여 패턴이 나타나는 횟수를 저장합니다.
- 3단계) count를 하기 위해 우선 모든 닉네임에 대해 포함된 패턴을 확인합니다.
- 4단계) 패턴이 포함된 횟수를 각각 카운트합니다.
- 5단계) 중복패턴만을 담은 배열을 생성합니다.
- 6단계) 중복패턴을 포함하는 아이디만을 담은 배열 생성
- 7단계) 중복을 제거하고 오름차순으로 정렬한 배열을 반환합니다.
아쉬운 점
- 로직을 잘 생각하면 단계를 줄이거나
- 중복되는 이중 for문의 사용을 두 번으로 줄일 수 있을 것 같습니다.
function problem6(forms) {
let nicknameSet = new Set([]);
// 1단계) 모든 연속되는 패턴을 찾아 집합으로 만들기 ===> ex) ["제이", "이엠", ~]
for (let i = 0; i < forms.length; i++) {
let nickname = forms[i][1];
for (let j = 0; j < nickname.length - 1; j++) {
nicknameSet.add(nickname[j] + nickname[j + 1]);
}
}
// 2단계) 패턴이 몇 번 나타나는지 count 하기위해 [pattern, 0] 배열을 생성
const patternArray = [...nicknameSet];
for (let i = 0; i < patternArray.length; i++) {
patternArray[i] = [patternArray[i], 0];
}
const includedPatternArray = [];
// 3단계) count를 하기 위해 모든 닉네임에 대해 포함된 패턴을 확인
for (let i = 0; i < forms.length; i++) {
for (let k = 0; k < patternArray.length; k++) {
let pattern = patternArray[k][0];
if (forms[i][1].includes(pattern)) {
includedPatternArray.push([forms[i][0], pattern]);
}
}
}
// 4단계) 패턴이 포함된 횟수를 각각 카운트 ===> ex) [pattern1, 0], [pattern2, 2], [pattern3, 3]
for (let i = 0; i < patternArray.length; i++) {
for (let k = 0; k < includedPatternArray.length; k++) {
if (patternArray[i][0].includes(includedPatternArray[k][1])) {
patternArray[i][1] += 1;
}
}
}
// 5단계) 중복패턴만을 담은 배열 생성 => [pattern, 2이상]
const repetitionArray = patternArray.filter((el) => el[1] >= 2);
// 6단계) 중복패턴을 포함하는 아이디만을 담은 배열 생성 ===> ex) ["jm@email.com", "jason@email.com", ~]
const resultIdArray = [];
for (let i = 0; i < includedPatternArray.length; i++) {
for (let j = 0; j < repetitionArray.length; j++) {
if (includedPatternArray[i][1].includes(repetitionArray[j][0])) {
resultIdArray.push(includedPatternArray[i][0]);
}
}
}
// 7단계) 중복을 제거하고 오름차순으로 정렬한 배열을 반환
const result = new Set([...resultIdArray]);
return [...result].sort();
}
module.exports = problem6;
리팩토링 전 코드
function problem6(forms) {
let nicknameSet = new Set([]);
for (let i = 0; i < forms.length; i++) {
let nickname = forms[i][1];
for (let j = 0; j < nickname.length - 1; j++) {
nicknameSet.add(nickname[j] + nickname[j + 1]);
}
}
const patternArray = [...nicknameSet];
for (let i = 0; i < patternArray.length; i++) {
patternArray[i] = [patternArray[i], 0];
}
const includedPatternArray = [];
for (let i = 0; i < forms.length; i++) {
for (let k = 0; k < patternArray.length; k++) {
let pattern = patternArray[k][0];
if (forms[i][1].includes(pattern)) {
includedPatternArray.push([forms[i][0], pattern]);
}
}
}
for (let i = 0; i < patternArray.length; i++) {
for (let k = 0; k < includedPatternArray.length; k++) {
if (patternArray[i][0].includes(includedPatternArray[k][1])) {
patternArray[i][1] += 1;
}
}
}
const repetitionArray = patternArray.filter((el) => el[1] >= 2);
const resultIdArray = [];
for (let i = 0; i < includedPatternArray.length; i++) {
for (let j = 0; j < repetitionArray.length; j++) {
if (includedPatternArray[i][1].includes(repetitionArray[j][0])) {
resultIdArray.push(includedPatternArray[i][0]);
}
}
}
const result = new Set([...resultIdArray]);
return [...result].sort();
}
module.exports = problem6;
리팩토링 후 코드
- Set 객체 대신 Object를 활용하여 코드마다 중복되던 역할들을 간소화
function problem6(forms) {
const nicknameObject = {};
for (let i = 0; i < forms.length; i++) {
for (let j = 0; j < forms[i][1].length - 1; j++) {
let pattern = forms[i][1][j] + forms[i][1][j + 1];
nicknameObject[pattern] = 0;
}
}
const nicknameArray = Object.keys(nicknameObject);
for (let i = 0; i < forms.length; i++) {
for (let j = 0; j < nicknameArray.length; j++) {
if (forms[i][1].includes(nicknameArray[j])) {
nicknameObject[nicknameArray[j]] += 1;
}
}
}
const countArray = Object.entries(nicknameObject);
const duplicationArray = countArray.filter((el) => el[1] > 1);
const resultArray = [];
for (let i = 0; i < forms.length; i++) {
for (let j = 0; j < duplicationArray.length; j++) {
if (forms[i][1].includes(duplicationArray[j][0])) {
resultArray.push(forms[i][0]);
}
}
}
const orderedResult = new Set([...resultArray]);
const removedArray = [...orderedResult].sort();
return removedArray;
}
module.exports = problem6;
'우테코 프리코스 > 1주차' 카테고리의 다른 글
우테코 프리코스 1주차 - 느낀점 (0) | 2022.11.03 |
---|---|
우테코 프리코스 1주차 - 문제 7 (리팩토링O) (0) | 2022.11.01 |
우테코 프리코스 1주차 - 문제 5 (리팩토링O) (0) | 2022.10.29 |
우테코 프리코스 1주차 - 문제 4 (리팩토링O) (0) | 2022.10.29 |
우테코 프리코스 1주차 - 문제 3 (0) | 2022.10.29 |