차근차근 구현해 나가봅시다.
일단 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.
const agg = genres.reduce((m, genre, index) => {
m[genre] = m[genre] || { playtime: 0, music: [] };
m[genre].playtime += plays[index]; // 플레이 시간 누적
m[genre].music.push([index, plays[index]]); // 어떤 음악이 있는지 기록(인덱스와 플레이 시간)
return m;
}, {});
// 가공 후의 agg의 모습
agg = {
rock: {
playtime: 200
music: [[0, 100], [2, 100]]
},
pop: {
playtime: 500,
music: [[1, 100], [3, 200], [4, 300]]
}
}
그 다음 agg를 playtime을 기준으로 내림차순 정렬을 합니다. (2번 조건 충족)
const sort = Object.values(agg).sort((a, b) => b.playtime - a.playtime)
// 정렬 후 sort의 모습
sort = [{ playtime: 500, music: [[1, 100], [3, 200], [4, 300]] }, { playtime: 200, music: [[0, 100], [2, 100]] }
이젠 music을 플레이 시간 기준으로 내림차순 정렬해서 장르별로 두 개씩만 뽑아내면 되겠네요.
플레이 시간이 같아도 고유 번호가 낮은 음악이 먼저 선택되는 건 보장되니 굳이 정렬 안해도 됩니다.
(1번 조건, 3번 조건, 4번 조건 충족)
const album = sort.reduce((m, genre) => {
// 플레이 시간 기준으로 내림차순 정렬
genre.music.sort((a, b) => b[1] - a[1]);
// 두 개씩 모으기
return m = m.concat(genre.music.slice(0, 2).map(v => v[0]));
}, []);
총 정리를 하면
1. 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.
2. 저장한 집합을 playtime을 기준으로 내림차순 정렬을 합니다.
3. 정렬한 집합에서 music을 플레이 시간 기준으로 내림차순 정렬해서 두 개씩 뽑아냅니다.
function solution(genres, plays) {
// 1. 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.
return Object.values(genres.reduce((m, genre, index) => {
m[genre] = m[genre] || { playtime: 0, music: [] };
m[genre].playtime += plays[index];
m[genre].music.push([index, plays[index]]);
return m;
}, {}))
// 2. 저장한 집합을 playtime을 기준으로 내림차순 정렬을 합니다.
.sort((a, b) => b.playtime - a.playtime)
// 3. 정렬한 집합에서 music을 플레이 시간 기준으로 내림차순 정렬해서 두 개씩 뽑아냅니다.
.reduce((m, genre) => {
genre.music.sort((a, b) => b[1] - a[1]);
return m = m.concat(genre.music.slice(0, 2).map(v => v[0]));
}, []);
}