[프로그래머스] 베스트앨범

정예원·2021년 8월 5일
0

문제풀이

목록 보기
9/9
post-thumbnail

https://programmers.co.kr/learn/courses/30/lessons/42579

문제풀이

장르별로 가장 많이 재생된 노래를 두개씩 모아 베스트 앨범 출시하는 문제이다.
해당 문제는 객체를 이용하였다.

1. 장르와 재생횟수를 dictionary 형식으로 구현

  • 장르별로 묶어준다
    {장르 : [[재생횟수, 고유번호], ... ], 장르 : [[재생횟수, 고유번호], ... ]}

장르와 재생 횟수 리스트를 위와 같은 형식으로 만들어 return해주는 함수이다.

    const makeDictionary = (genres, plays) => {
      const dict = {};

      for (let i = 0; i < genres.length; i++) {
          if (genres[i] in dict) { //이미 dict에 있다면 해당 배열에 추가
              dict[genres[i]].push([plays[i], i]); 
          } else { //없다면 새로 만든다.
              dict[genres[i]] = [[plays[i], i]];
          }
      }

      return dict;
   }    

2. 장르 내에서 많이 재생된 노래순으로 정렬

a. 같은 장르 안에서 재생횟수로 내림차순으로 정렬해준다.
b. 재생횟수가 같다면 고유번호가 낮은 노래부터 정렬
const sortDictionary = (dict) => {
    const PLAY = 0;
    const NUMBER = 1;

    for (const [genre, playList] of Object.entries(dict)) {
        console.log(playList);
        dict[genre] = playList.sort((a, b) => {
            return a[PLAY] === b[PLAY] ? a[NUMBER] - b[NUMBER] : b[PLAY] - a[PLAY];
        });
    }

    return dict;
};

3. 장르마다의 합을 구한 후 정렬 (내림차순)

장르마다 합을 구해 합과 장르를 하나의 원소로 갖는 객체를 생성
{장르이름: 재생 합, 장르이름: 재생 합...}

    const totalPlayDict = {};
    for (const [genre, playList] of Object.entries(dict)) {
        let sum = 0;
        for (const [play, _] of playList) sum += play;
        totalPlayDict[genre] = sum;
    }


정렬

    const sortedTotalPlayDict = Object.fromEntries(Object.entries(totalPlayDict).sort(([, a], [, b]) => b - a));

4. 장르이름으로 2번에서 정렬된 객체에 접근, 앞에서 두개 뽑아서 answer에 고유번호 추가

    for (const genre of Object.keys(sortedTotalPlayDict)) {
        const selectedNumberList = sortedDict[genre].slice(0, 2).map((item) => item[NUMBER]);
        answer.push(...selectedNumberList);
    }

전체코드

function solution(genres, plays) {
    let answer = [];
    const dict = makeDictionary(genres, plays);
    const sortedDict = sortDictionary(dict);
    const NUMBER = 1;

    const totalPlayDict = {};
    for (const [genre, playList] of Object.entries(dict)) {
        let sum = 0;
        for (const [play, _] of playList) sum += play;
        totalPlayDict[genre] = sum;
    }
    const sortedTotalPlayDict = Object.fromEntries(Object.entries(totalPlayDict).sort(([, a], [, b]) => b - a));

    for (const genre of Object.keys(sortedTotalPlayDict)) {
        const selectedNumberList = sortedDict[genre].slice(0, 2).map((item) => item[NUMBER]);
        answer.push(...selectedNumberList);
    }

    return answer;
}

const makeDictionary = (genres, plays) => {
    const dict = {};

    for (let i = 0; i < genres.length; i++) {
        if (genres[i] in dict) {
            dict[genres[i]].push([plays[i], i]);
        } else {
            dict[genres[i]] = [[plays[i], i]];
        }
    }

    return dict;
};

const sortDictionary = (dict) => {
    const PLAY = 0;
    const NUMBER = 1;

    for (const [genre, playList] of Object.entries(dict)) {
        dict[genre] = playList.sort((a, b) => {
            return a[PLAY] === b[PLAY] ? a[NUMBER] - b[NUMBER] : b[PLAY] - a[PLAY];
        });
    }

    return dict;
};

배운점

1. JavaScript의 sort()는 문자열을 정렬한다.

숫자를 정렬할 때 기본 동작은 올바르게 정렬되지 않는다. 따라서 숫자 정렬시에는 아래와 같은 코드로 작성한다.
sort((a,b) => (a-b))

2. 두 개의 배열을 합치려면 전개연산자를 사용한다.

... spread operator (전개연산자) 란?

  • ES6에서 제공하는 spread operator(...)를 사용하여 배열을 이어 붙일 수 있다.
  • spread operator는 배열과 객체 등 여러 곳에서 사용할 수 있다.
  • 배열에서 spread operator는 배열의 원소들을 분해해서 개별요소로 만들어준다.
    예제
    answer.push(...selectedNumberList);

Reference

https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting#recentComments
https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html

profile
hello world!

0개의 댓글