일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Frontend Roadmap
- 프로그래머스 데브코스 프론트엔드
- 모던 자바스크립트 딥다이브
- 인프런 자바스크립트 알고리즘 문제풀이
- 우테캠 회고록
- frontend roadmap study
- 프로그래머스 데브코스 프론트엔드 TIL
- KDT 프로그래머스
- 프로그래머스 K_Digital Training
- 리팩토링 회고
- 프로그래머스 K_Digital Training 프론트엔드
- 모던 javascript Deep Dive
- KDT 프로그래머스 데브코스 프론트엔드
- Vue3 Router
- 백준 js
- react 프로젝트 리팩토링
- 프로그래머스 데브코스
- react customHook 예시
- useRef 지역 변수
- 머쓱이
- useEffect return
- 모던 자바스크립트 Deep Dive TIL
- 투포인터알고리즘 js
- TypeScript 문법 소개
- 개발자 특강
- Vue3
- K_Digital Training
- 모던 자바스크립트 TIL
- 백준 node.js
- 모던 자바스크립트 Deep Dive
- Today
- Total
프론트엔드 개발자의 기록 공간
[프로그래머스 JavaScript] 신고 결과 받기 본문
🚩 신고 결과 받기 JS
📖 문제 설명 : 일반 유저가 악성 유저를 신고할 수 있다. 사용자가 지정한 신고 횟수 이상으로 신고를 당한 악성 유저는 차단을 당하고, 차단 당한 사실을 신고한 유저에게 메일로 알려줘야 한다. 프로그래머스 문제
💡 Map, Set 객체를 이용한다.
처음 해결한 코드
function solution(id_list, report, k) {
let answer = []
let idMap = new Map()
// key : id_list,
// value : {reportList : 유저가 신고한 ID 목록, cnt : 자신이 신고 당한 횟수, mail : 메일을 받을 횟수}
id_list.forEach((el) => idMap.set(el, { reportList: [], cnt: 0, mail: 0 }))
report.forEach((el) => {
let [userId, reportId] = el.split(' ')
let reportValue = idMap.get(userId)
let cntValue = idMap.get(reportId)
// 한 유저가 같은 유저 여러 번 신고하는 경우 처리
// 유저 ID에 유저가 신고한 ID가 포함되지 않을 경우(아직 신고한 적이 없을 경우)만
// 신고한 ID를 찾아 자신이 신고 당한 횟수 카운트
if (![...reportValue.reportList].includes(reportId)) {
idMap.set(reportId, {
reportList: cntValue.reportList,
cnt: cntValue.cnt + 1,
mail: 0,
})
}
// 유저 ID를 찾아 유저가 신고한 ID 추가
// Set 객체를 통해 중복 제거
idMap.set(userId, {
reportList: new Set([...reportValue.reportList, reportId]),
cnt: reportValue.cnt,
mail: 0,
})
})
// 정지 userId 판별
let blackList = []
for (let [key, value] of idMap) {
if (value.cnt >= k) {
blackList.push(key)
}
}
// 메일 발송 갯수 카운트
// 유저가 신고한 ID에 정지 ID가 포함되는 경우 유저 mail 값 카운트
blackList.forEach((id) => {
for (let [key, value] of idMap) {
if ([...value.reportList].includes(id)) {
idMap.set(key, {
reportList: value.reportList,
cnt: value.cnt,
mail: value.mail + 1,
})
}
}
})
// 메일 발송
for (let [key, value] of idMap) {
answer.push(value.mail)
}
return answer
}
const id_list = ['muzi', 'frodo', 'apeach', 'neo']
const report = [
'muzi frodo',
'apeach frodo',
'frodo neo',
'muzi neo',
'apeach muzi',
]
// console.log(solution(id_list, report, 2))
const id_list2 = ['con', 'ryan']
const report2 = ['ryan con', 'ryan con', 'ryan con', 'ryan con']
console.log(solution(id_list2, report2, 3))
👨💻 코드 설명
1. Map 객체를 이용해서(idMap) i 번째 유저가 신고한 ID, i 번째 유저 자기 자신이 신고 당한 횟수, i 번째 유저가 메일을 받을 횟수를 기억할 resportList, cnt, mail 변수를 선언한다.
2. 매개변수 report를 순회하면서, 자신이 신고 당한 횟수, 자신이 신고한 유저 정보를 저장한다.
3. 1,2번을 수행 후 idMap을 순회하면서 자신이 신고 당한 횟수가 K 횟수 이상일 때, 유저 이름을 블랙리스트 배열에 저장한다.
4. idMap을 순회하면서 신고한 유저 정보에 블랙리스트 id가 포함되면 해당 유저에게 메일을 보내야 하므로 메일 횟수를 카운트한다.
5. 메일 횟수만 따로 배열에 저장 후 return 해준다.
👉 문제는 풀었지만 로직이 너무 복잡하고 이해하기 어렵다.. 리팩토링을 위해 다른 사람의 풀이 참고
리팩토링 코드
function solution(id_list, report, k) {
let answer = []
// 중복 제거 후, 유저 ID, 유저가 신고한 ID 분리
let reports = [...new Set(report)].map((el) => el.split(' '))
// 신고 당한 ID Map
let reportId = new Map()
// 신고 당한 ID 카운트
for ([, report] of reports) {
reportId.set(report, reportId.get(report) + 1 || 1)
}
// 메일 발송 ID Map
let mailId = new Map()
// 메일 발송 갯수 카운트
for ([user, report] of reports) {
if (reportId.get(report) >= k) {
mailId.set(user, mailId.get(user) + 1 || 1)
}
}
// 메일 발송 추출 (없는 경우 0)
answer = id_list.map((id) => mailId.get(id) || 0)
return answer
}
const id_list = ['muzi', 'frodo', 'apeach', 'neo']
const report = [
'muzi frodo',
'apeach frodo',
'frodo neo',
'muzi neo',
'apeach muzi',
]
console.log(solution(id_list, report, 2))
const id_list2 = ['con', 'ryan']
const report2 = ['ryan con', 'ryan con', 'ryan con', 'ryan con']
console.log(solution(id_list2, report2, 3))
👨💻 코드 설명
1. Set 객체를 이용하여 문자열 자체를 중복 제거한다. 즉 동일한 유저가 동일한 다른 유저를 신고하는 경우를 처리한다. 그 후, 유저 ID, 유저가 신고한 ID를 분리하여 reports 배열에 저장한다.
2. reportId Map을 선언하여 신고 당한 ID를 카운트해준다.
3. mailId Map을 선언하여 신고 당한 ID가 K 횟수 이상일 때, mailId에 신고를 한 유저 ID 정보를 저장한다.
4. 메일 발송을 위해 id_list 순서대로 순회하며 메일 발송 횟수를 저장한 후 return 해준다.
👉 Set 객체가 문자열 자체도 중복 제거할 수 있는지 몰랐다. 그래서 중복 제거를 위한 로직이 훨씬 깔끔해졌다. 또한 유저 ID, 신고 당한 유저 ID, 메일 발송을 각각 분리하여 조합하고 비교를 통해 훨씬 깔끔하고 직관적이고 짧은 코드로 해결할 수 있었다. 다른 사람들의 코드를 보면서도 알고리즘 푸는데 많이 도움 되는 것 같다.
잘못된 설명, 코드, 예외 케이스가 있다면 댓글 남겨주시면 수정하겠습니다.
'알고리즘_JS > 프로그래머스_Level1' 카테고리의 다른 글
[프로그래머스 JavaScript] 최소직사각형 (0) | 2022.04.08 |
---|---|
[프로그래머스 JavaScript] 직사각형 별찍기 (0) | 2021.07.16 |
[프로그래머스 JavaScript] x만큼 간격이 있는 n개의 숫자 (0) | 2021.07.15 |
[프로그래머스 JavaScript] 행렬의 덧셈 (0) | 2021.07.15 |
[프로그래머스 JavaScript] 핸드폰 번호 가리기 (0) | 2021.07.15 |