각 장르마다 곡이 들어가 있다. 이때 각 장르별로 가장 재생이 많이 된 상위 2곡을 선정해서 앨범을 만들려고 한다. 예시를 살펴보자
genres plays return
["classic", "pop", "classic", "classic", "pop"] [500, 600, 150, 800, 2500] [4, 1, 3, 0]
우선 제일 많이 재생된 장르 순으로 곡 2개가 담긴다. pop(3,100회 재생 됨) , classic(1,450회 재생 됨) 이므로 pop에서 가장 많이 재생된 곡 2개가 먼저 담긴다.
이때 재생된 횟수가 높은것이 먼저 담긴다.(4,1)
재생횟수가 같다면 고유번호가 적은것이 먼저 담긴다.
장르내에서 재생된 곡이 1개밖에 없다면 그걸 담는다.
두 가지 solution이 있다. 두개다 기가막힌 solution이다.
function solution1(genres, plays) {
let dic = {};
genres.forEach((t, i) => {
dic[t] = dic[t] ? dic[t] + plays[i] : plays[i];
});
let dupDic = {}; // 장르당 곡이 3개넘어가는게 있는지 판별하기 위함.
return genres
// 장르, 재생수, 고유번호를 각각 담음. sort할때 쓰려고.
.map((t, i) => ({ genre: t, count: play[i], index: i }))
// sort의 다중정렬 가능.
.sort((a, b) => {
// 장르가 다르면 위의 dic을 사용하여 가장 인기있는 장르를 토대로 내림차순정렬
if (a.genre !== b.genre) return dic[b.genre] - dic[a.genre];
// 장르가 같으면 재생수를 비교해서 내림차순 정렬
if (a.count !== b.count) return b.count - a.count;
// 재생수도 같으면 고유번호로 내림차순 정렬
return a.index - b.index;
});
// 장르 내에서 상위 랭크 2개만 선정하고 나머지는 false를 통해 걸러짐.
// dupDic 에서 장르의 갯수가 담김.
.filter((t,i)=>{
if(dupDic[t.genre] >=2) return false
dupDic[t.genre] = dupDic[t.genre]?dupDic[t.genre] +1:1
return true
// 최종적으로 정렬되고 걸러진 상태에서 고유번호만 순서대로 추출하면 끝!
}).map(t => t.index)
}
filter전까지의 상황임
0: {genre: "pop", count: 2500, index: 4}
1: {genre: "pop", count: 600, index: 1}
2: {genre: "classic", count: 800, index: 3}
3: {genre: "classic", count: 150, index: 0}
4: {genre: "classic", count: 150, index: 2}
여기서 마지막에 클래식 obj는 필터링되서 없어짐. 장르당 가장 많이 재생된것 2개만 있어야 하므로.
깔끔 그 자체다...
크... 외국어를 유창하게 하는 사람을 보는것 같은 느낌..섹시하다.
깔끔 세련 편함 그냥 기분좋게 하는 요소는 다들어가 있다고 보면 됨.
요걸 계속 적어보면서 연습하자. sort,filter,map 잘 사용했고, obj도 적절히 잘 사용한 것 같다.
function solution2(genre, plays) {
let answer = [];
let songs = genres.map((genre, index) => {
return {
no: index,
genre: genre,
play: plays[index],
};
});
let genrePlayCnt = [];
// 장르와 재생된 횟수를 합산해서 genrePlayCnt에 push함
songs.forEach((song) => {
let thisGenre = genrePlayCnt.find(
(genrePlay) => genrePlay.genre === song.genre
);
if (!thisGenre) {
genrePlayCnt.push({
genre: song.genre,
play: song.play,
});
} else thisGenre.play += song.play;
});
// 장르 통틀어서 재생된 횟수를 내림차순으로 정렬
genrePlayCnt.sort((a, b) => b.play - a.play);
genrePlayCnt.forEach((genrePlay) => {
// genrePlayCnt에서 정렬한 대로 하나씩 loop함
// pop이 먼저이므로 pop에 해당하는 song만 뽑아내서 thisGenreSongs에 저장
let thisGenreSongs = songs.filter((song) => song.genre === genrePlay.genre);
});
// 플레이 순으로 내림차순. 자동으로 고유번호랑 같이 정렬됨
thisGenreSongs.sort((a, b) => b.play - a.play);
// 제일 많이 플레이된곡의 고유번호를 answer에 push
answer.push(thisGenreSongs[0].no);
// 그 다음 2번째 곡이 있으면 2번째 곡의 고유번호를 push함
if (thisGenreSongs.length > 1) {
answer.push(thisGenreSongs[1].no);
}
return answer;
}
첫 번째 만큼 깔끔한건 아니지만 나름 로직을 잘 정리해서 구현했다.
obj를 이용해서 정보를 잘 정리하고 필요할때마다 뽑아쓰는 기술이 돋보임.
그냥 두개다 너무 친근하고 깔끔한 느낌이다.
진짜 오늘 또 느낀다. 매일 느낀다. 너무 감사하고 신기하고 뿌듯하다...눈물나올것 같다.