목표

문제 요구사항

  1. 속한 노래가 가장 많이 재생된 장르를 수록합니다.
  2. 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
  3. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.

문제 풀이

최대한 변수를 많이 선언하지 않는 방향으로 풀이

  1. 데이터 추상화
    genres,plays 값이 다른 두개의 데이터로 내려온다.
    문제를 해결하기 위해서는 하나의 데이터로 묶어 줄 필요가 있다. 또한 장르 내에서 많이 재생된 노래 순으로 수록 하기 때문에 장르별 재생 횟수도 값이 있어야 한다. 마지막으로 장르 내에서 재생횟수를 기준으로 노래를 수록 해야하기 때문에 노래별 재생 횟수값도 가지고 있는 데이터로 추상화 하자.

     // 모든 노래 데이터 
     const musics = genres.reduce( ( genresList, val, idx) => {
         // console.log( genresList, val, idx);
         if(!genresList[val]){
             genresList[val] = { totalPlays : plays[idx], plays : [ [idx, plays[idx] ]]}
         }else {
             genresList[val].totalPlays += plays[idx];
             genresList[val].plays = [ ...genresList[val].plays, [idx, plays[idx]] ]
         }
         return genresList;
     }, {})
     // 장르 크기 정렬된 노래 데이터 
     const genreOrderedMusics = Object.values(musics).sort( (a, b) => {
         return b.totalPlays - a.totalPlays;
     })
    
     console.log( genreOrderedMusics );
    
     => 실행결과 
    
     [
       { totalPlays: 3100, plays: [ [Array], [Array] ] },
       { totalPlays: 1450, plays: [ [Array], [Array], [Array] ] }
     ]
    
    
  2. 문제 해결

    1. 장르별 재생횟수가 많은 순서대로 데이터를 만들었으므로 요구사항 1.은 해결.
    2. 요구사항 2.를 해결하기 위해서는 받은 데이터의 plays의 크기별로 정렬 한다.
    3. 요구사항 3.를 해결하기 위해서는 2.번에서 정렬할때 낮은 번호 순으로 정렬되도록 구현 한다.
     // 베스트 엘범에 들어갈 고유 번호 구하는 로직 
     genreOrderedMusics.forEach((genre) => {
         // 장르 내에서 많이 재생된 노래 순으로 정렬
         // 크기 같은 경우는 따로 처리 불필요. 배열이 낮은순으로 있기 때문
         genre.plays.sort((a,b) => {
             return b[1] - a[1];
         } ) 
            
         // 재생 회수 별로 수록. 고유번호가 낮은 경우 어케됨?
         if(genre.plays.length > 1 ){
             answer = [ ...answer, genre.plays[0][0], genre.plays[1][0]];
         }else {
             answer = [ ...answer, genre.plays[0][0] ]
         }
     })
    
     console.log(answer)
    

결론

다른 사람의 기가막힌 풀이..

function solution(genres, plays) {
    var dic = {};
    genres.forEach((t,i)=> {
        dic[t] = dic[t] ?  dic[t] + plays[i] :plays[i];        
    });

    var dupDic = {};
    return genres          
          .map((t,i)=> ({genre : t, count:plays[i] , index:i}))
          .sort((a,b)=>{               
               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;
           })
           .filter(t=>  {
               if(dupDic[t.genre] >= 2) return false;
               dupDic[t.genre] = dupDic[t.genre] ? dupDic[t.genre]+ 1 : 1;
               return true;
            })
           .map(t=> t.index);    
}


최초 연습 풀이

  1. 데이터 추상화 genres, plays 두개의 다른 배열로 값이 내려온다.
    이 두개의 배열을 합쳐 하나의 데이터로 만들어주자
const songs = genres.map( (ele, idx) => {
    return { genre : ele , idx : idx, plays : plays[idx] } 
});
console.log( songs);

=>  실행 결과 
  [
    { genre: 'classic', idx: 0, plays: 500 },
    { genre: 'pop', idx: 1, plays: 600 },
    { genre: 'classic', idx: 2, plays: 150 },
    { genre: 'classic', idx: 3, plays: 800 },
    { genre: 'pop', idx: 4, plays: 2500 }
  ]

장르별 재생 횟수를 알아야 가장 많이 재생된 장르를 먼저 수록할수 있기 때문에 장르별 재생 횟수를 가진 데이터를 만들자.

// 장르 별 재생 횟수 데이터 
const genresPlays = genres.reduce((genresList, g, i) => {
    if (!genresList[g]) {
        genresList[g] = plays[i];
    } else {
        genresList[g] += plays[i];
    }
    return genresList;
}, {});
console.log(genresPlays)

=> 실행 결과
  { classic: 1450, pop: 3100 }