일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 파이썬 정렬
- 이것이 취업을 위한 코딩 테스트다
- sort()
- 기억장치
- 파이썬 연산자
- GIT
- IT5분잡학사전
- RARP
- 노마드코더
- data type
- icmp
- 컴퓨터 동작방식
- 데이터 통신과 컴퓨터 네트워크
- 쉽게 배우는 데이터 통신과 컴퓨터 네트워크
- ARP
- 쿠키
- 파이썬 자료형
- 이코테
- 시스템 소프트웨어
- 리스트
- 데이터통신
- OSI7계층모델
- 자료형
- 북클럽
- 라우팅
- 이것이 취업을 위한 코딩테스트다
- 노개북
- CS
- 컴퓨터네트워크
- DP
- Today
- Total
뚝딱햄 탈출기
[JS][TIL] reduce()를 사용해보자 : 프로그래머스 베스트앨범 본문
[JS][TIL] reduce()를 사용해보자 : 프로그래머스 베스트앨범
hyrmzz1 2024. 4. 3. 21:42[프로그래머스][level 3] 베스트앨범
접근 방식
- 입력값이 두 배열 genres와 plays로 나뉘어 들어오지만, 두 배열의 같은 인덱스를 가진 값들은 하나의 노래에 대한 값이다.
- 따라서 한 객체에 노래에 대한 정보들을 모아야겠다고 생각했다.
- 먼저 Object에 노래의 고유번호(= 인덱스), 장르, 재생 횟수를 담는다.
- 반환값인 베스트앨범의 첫 번째 기준은 '속한 노래의 재생 횟수가 많은 장르 먼저 수록' 이므로
장르별로 해당 장르 노래들의 재생 횟수를 모두 더하고, 총 재생 횟수를 기준으로 장르를 내림차순 정렬해야겠다고 생각했다. - 베스트앨범의 두 번째 기준은 '장르 내에서 많이 재생 횟수가 많은 노래 수록' 이다.
장르별로 속한 노래들을 재생 횟수를 기준으로 내림차순 정렬해야겠다고 생각했다. - 장르를 (4)에서 구한 총 재생 횟수 기준으로 내림차순 정렬하고,
순회하며 장르별로 재생 횟수가 top1, 2인 노래의 인덱스를 출력하자.- 각 장르당 2개 이하의 노래를 담아야 한다. -> 카운트해야 함!
- 인덱스는 배열에 담아 출력해야 한다.
Object의 각 요소에 대해 1) 장르별로 분류하고 2) 재생 횟수를 더해야 하는데,
복잡한 방식밖에 떠오르지 않아 내 사랑 gemini에게 자문한 결과 reduce()
를 사용하라는 답변을 받았다.
🤔 reduce()란?
reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서 (reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
리듀서 함수는 네 개의 인자를 가집니다.
1. 누산기 (acc)
2. 현재 값 (cur)
3. 현재 인덱스 (idx)
4. 원본 배열 (src)
리듀서 함수의 반환 값은 누산기에 할당되고, 누산기는 순회 중 유지되므로 결국 최종 결과는 하나의 값이 됩니다.
콜백의 최초 호출 때 accumulator와 currentValue는 다음 두 가지 값 중 하나를 가질 수 있습니다.
1. initialValue를 제공한 경우, accumulator는 initialValue와 같고 currentValue는 배열의 첫 번째 값과 같습니다.
2. initialValue를 제공하지 않았다면, accumulator는 배열의 첫 번째 값과 같고 currentValue는 두 번째와 같습니다.
1. 두 개의 인자를 가질 때
[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr);
// 1번째 콜백 호출) prev: 0, curr: 1. 반환 값 = 1
// 2번째 콜백 호출) prev: 1, curr: 2. 반환 값 = 3
// 3번째 콜백 호출) prev: 3, curr: 3. 반환 값 = 6
// 4번째 콜백 호출) prev: 6, curr: 4. 반환 값 = 10
// 10 반환
첫 번째 인자인 prev는 acc로, 누적되는 값이다.
두 번째 인자인 curr는 cur으로, 현재 처리하고 있는 요소이다. (현재 순회 중인 요소)
이 코드에는 initialValue가 제공되지 않았으므로 콜백의 최초 호출 때 prev에 배열의 첫 번째 값인 0을 할당하고, curr에는 두 번째 값인 1을 할당한다.
두번째 호출부턴 prev에 이전 호출의 반환값이 들어가고, curr에는 배열의 나머지 원소인 2, 3, 4가 순차적으로 들어간다.
결과적으로 reduce()는 마지막 콜백 호출의 반환값을 반환한다.
2. 초기값이 주어졌을 때
초기값이 주어졌다면 acc는 초기값과 같고 cur은 배열의 첫 번째 값과 같다.
[0, 1, 2, 3].reduce(
(accumulator, currentValue) => accumulator + currentValue,
10,
);
10이라는 초기값이 주어졌으니 콜백의 최초 호출 때 accumulator에 10이, currentValue에 0이 들어간다.
반환값인 10 + 0, 즉 10이 두번째 콜백 호출 때 accumulator에 들어가고, 배열의 다음 원소인 1이 currentValue에 들어간다.
3. 객체로 이루어진 배열에 reduce()를 사용하려면?
객체로 이루어진 배열에 들어있는 값을 합산하려면 반드시 초기값이 필요하다고 한다.
초기값으로 {}만 할당할 수도 있다!
코드를 작성하며 객체에 적용하는 법을 알아보자.
✅ Solution
장르에 대한 총 누적값(재생 횟수)을 구해야 한다. 초기값은 필요 없다고 생각해 {}를 할당했다.
누적값 acc를 배열로도 취급할 수 있다!
각 장르별로 누적값을 구해야 하므로 acc[song.genre]에 song.play를 더해주었다.
function solution(genres, plays) {
let songs = genres.map((genre, idx) => {
return {
idx: idx,
genre: genre,
play: plays[idx],
};
})
// 장르별 재생 횟수
let playByGenre = songs.reduce((acc, song) => {
if (!acc[song.genre]) { // 초기값 설정
acc[song.genre] = 0;
}
acc[song.genre] += song.play;
return acc;
}, {});
// 총 재생횟수 높은 순으로 장르 정렬
playByGenre = Object.entries(playByGenre).sort((a, b) => b[1] - a[1]);
// 재생횟수 높은 순으로 모든 노래 정렬
songs.sort((a, b) => b.play - a.play);
// 기준을 만족하는 노래의 인덱스 넣기
const answer = [];
playByGenre.forEach((genre) => {
let limit = 0;
songs.forEach((song) => {
if (song.genre === genre[0] && limit < 2) {
answer.push(song.idx);
limit++;
}
})
})
return answer;
}
총 재생 횟수 높은 순으로 장르 정렬 단계 전에 playByGenre를 출력해 보면 {"classic":1450,"pop":3100}
와 같다.
object인 playByGenre를 play(1450, 3100) 기준으로 내림차순 정렬하기 위해 Object.entries()를 통해 [key, value] 쌍의 배열로 만들었다. 배열이 됐으므로 인덱스를 통해 play를 기준으로 정렬할 수 있다. .sort((a, b) => b[1] - a[1]);
배열로 만든 덕에 answer에 노래의 인덱스를 넣기 위한 forEach문을 더 수월하게 작성할 수 있었다!
https://school.programmers.co.kr/learn/courses/30/lessons/42579
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
'Algorithm & Data structure > 알고리즘 문제 풀이' 카테고리의 다른 글
[JS][TIL] DFS를 이용한 순열구하기 : 프로그래머스 피로도, 소수 찾기 (0) | 2024.04.11 |
---|---|
[Python][백준 BOJ Silver I] 1932. 정수 삼각형 : DP (0) | 2024.02.28 |
[Python][백준 BOJ ] 10815. 숫자 카드 : 시간 초과 해결, 딕셔너리 vs 리스트, 이분 탐색 (1) | 2024.01.08 |
[Python][BOJ 백준][Silver II] 1406. 에디터, [Gold IV] 9935. 문자열 폭발 : 스택 아이디어 떠올리기 (0) | 2024.01.03 |
[Python][백준 BOJ Silver IV] 1269. 대칭 차집합 : set 자료형을 이용한 교집합/합집합/차집합 구하기 (1) | 2024.01.02 |