[프로그래머스/js] 베스트 앨

이다형·2023년 7월 17일
0

나의 풀이

(여러 velog와 티스토리 코드를 참조하여 풀었음을 밝힙니다.)

function solution(genres, plays) {
  //장르별 plays수를 합산한 객체
    const genreCounts = genres.reduce((acc, genre, idx) => {
        acc[genre] = (acc[genre] || 0) + plays[idx];
        return acc;
    }, {});
    
  //genreCounts 딕셔너리의 키로 이루어진 요소를 밸류값으로 내림차순 정렬
    const genList = Object.keys(genreCounts).sort((a, b) => genreCounts[b] - genreCounts[a]);
    
   //장르, 인덱스, 플레이수가 포함된 객체 
    const info = genres.map((g, i) => ({
        Genre: g,
        Index: i,
        Plays: plays[i]
    })).sort((a, b) => b.Plays - a.Plays);
    
  //장르 리스트의 장르마다 반복한다
  //현재반복의 장르(g) 값들을 순서대로 객체에 넣는다. filter()
  //그값들을 앞에서부터 2개 자른다.   slice()
  //그값들의 인덱스값만 배열로 반환해준다.   map()
  //flatMap() 이므로 모든값이 1차원 배열로 반환
  
    const answer = genList.flatMap(g => 
                                   info.filter(x => x.Genre === g)
                                   .slice(0, 2)
                                   .map(({ Index }) => Index));
    
    return answer;
}

상세 설명

const genreCounts = genres.reduce((acc, g, idx) => {
        acc[] = (acc[g] || 0) + plays[idx];
        return acc;
    }, {});
{ classic: 1450, pop: 3100 }

먼저 어떤 장르가 총 재생수가 많은지 알 필요가 있다.
reduce로 genres배열의 인덱스와 동일한 plays의 인덱스를 더한 객체를 반환한다.
(acc[g] || 0) 는 만약 acc[g]가 null일때 0을 선택한 값의 연산을 수행한다.

const genList = Object.keys(genreCounts).sort((a, b) => genreCounts[b] - genreCounts[a]);
[ 'pop', 'classic' ]
//총 플레이수 합산이 높은 순서대로 담긴 genList 배열

genreCouns의 key를 해당하는 value의 내림차순으로 정렬한 genList를 반환한다.

const info = genres.map((g, i) => ({
      Genre: g,
      Index: i,
      Plays: plays[i]
    })).sort((a, b) => b.Plays - a.Plays);
[
  { Genre: 'pop', Index: 4, Plays: 2500 },
  { Genre: 'classic', Index: 3, Plays: 800 },
  { Genre: 'pop', Index: 1, Plays: 600 },
  { Genre: 'classic', Index: 0, Plays: 500 },
  { Genre: 'classic', Index: 2, Plays: 150 }
].sort((a, b) => b.Plays - a.Plays);

genre의 이름, 인덱스, 플레이수 정보가 담긴 객체를 생성,
Plays를 기준으로 내림차순 정렬

이제 여기서 정렬과 추출을 통해 답을 도출하면 된다.

 const answer = genList.flatMap(g =>info.filter(x => x.Genre === g)
                                 .slice(0, 2).map(({ Index }) );

  return answer;
}

답 도출 과정

const answer = genList.flatMap(g => info.filter(x => x.Genre === g)
                               .slice(0, 2).map(({ Index }) => Index));

return answer;

1. genList [ 'pop', 'classic' ] 의 요소들에 대해 순서대로 순회하여 배열을 생성

genList.flatMap(g=>

2. info 객체의 Genre가 현재 g(genList의 장르)와 같은 info 객체들만 반환,

info.filter(x => x.Genre === g)
[
  { Genre: 'pop', Index: 4, Plays: 2500 },
  { Genre: 'pop', Index: 1, Plays: 600 },
  { Genre: 'classic', Index: 3, Plays: 800 },
  { Genre: 'classic', Index: 0, Plays: 500 },
  { Genre: 'classic', Index: 2, Plays: 150 }
]

genlist의 장르는 순서대로 [ 'pop', 'classic' ] 이기때문에
info Genre가 'pop'인 info들이 먼저 들어가고
그다음 요소인 'classic'에 해당하는 info들이 들어감

3. 장르별로 재생횟수가 높은 2개의 인덱스를 반환해야함,

.slice(0, 2)
  { Genre: 'pop', Index: 4, Plays: 2500 },
  { Genre: 'pop', Index: 1, Plays: 600 },
  { Genre: 'classic', Index: 3, Plays: 800 },
  { Genre: 'classic', Index: 0, Plays: 500 }

2번처럼 해당 장르의 모든 info를 담지않고 내림차순 정렬은 이미 되있으니 0번 인덱스부터 2개만 담아준다.

4. 해당 곡의 인덱스만 추출

.map(({ Index }) => Index))
[ 4, 1, 3, 0 ]

info.Index들만 남은배열이 flatMap으로 순회되어서 1차원배열로 반환되었다.

0개의 댓글