[js] 등수 매기기

sookyoung.k·2024년 7월 21일
1
post-thumbnail

영어 점수와 수학 점수의 평균 점수를 기준으로 학생들의 등수를 매기려고 합니다. 영어 점수와 수학 점수를 담은 2차원 정수 배열 score가 주어질 때, 영어 점수와 수학 점수의 평균을 기준으로 매긴 등수를 담은 배열을 return하도록 solution 함수를 완성해주세요.

제한사항

  • 0 ≤ score[0], score[1] ≤ 100
  • 1 ≤ score의 길이 ≤ 10
  • score의 원소 길이는 2입니다.
  • score는 중복된 원소를 갖지 않습니다.

나의 풀이

function solution(score) {
    // 평균 점수를 담을 빈 배열
    let scoreArr = [];
    // 평균점수와 랭킹 정보를 담은 객체를 담을 빈 배열 
    let result = [];
    
    // socore 배열을 돌면서 평균점수를 scoreArr에 넣어주고,
    // 각각의 평균 점수와 랭킹 정보는 0으로 초기화한 객체를 배열에 넣는다.
    for ([num1, num2] of score) {
        scoreArr.push((num1+num2)/2);
        result.push({avg: (num1+num2) / 2, rank: 0});
    };
    
    // 평균 점수를 내림차순 정렬
    scoreArr.sort((a, b) => b-a);
    // 일치하는 인덱스 번호 + 1로 rank값 갱신
    result.map((v, i) => {
        return v.rank = scoreArr.findIndex((e) => e === v.avg) + 1;
    })
    
    return result.map((v) => v.rank);
}
  1. soccorArr라는 빈 배열을 만들어서 각 학생들의 평균 점수를 저장한다.
  2. result라는 빈 배열을 만들어서 각 학생들의 평균 점수와 랭킹 정보를 담은 객체를 저장한다.
  3. score 배열을 순회하면서 각 학생의 평균 점수를 계산하여 scoreArr에 추가하고, result 배열에 평균 점수와 랭킹(초기값 0)을 가진 객체를 추가한다.
  4. scoreArr를 내림차순으로 정렬한다.
  5. result 배열의 각 객체에 대해서 scoreArr에서 해당 평균 점수의 인덱스번호 + 1을 rank 속성에 할당한다.
  6. 최종적으로 result 배열의 rank 속성들만 추출하여 반환한다.

하지만... 이 코드는 잘못되었다! map은 새로운 배열을 반환하는데, 이 코드에서는 그 반환값을 사용하지 않는다. 원본 배열을 변경하지도 않는다. 이 코드에서는 result 배열의 각 요소를 직접 수정하는 것이 목적이기 때문에 map() 메서드가 아니라 forEach() 메서드를 사용해야 한다.

수정된 부분은 다음과 같다.

    // 일치하는 인덱스 번호 + 1로 rank값 갱신
    // result.map((v, i) => {
    //     return v.rank = scoreArr.findIndex((e) => e === v.avg) + 1;
    // });
    result.forEach((v, i) => {
        v.rank = scoreArr.findIndex((e) => e === v.avg) + 1;
    });
    
    return result.map((v) => v = v.rank);

뭐 다른 개선사항들도 있겠지만! 일단 map()을 써야 할 때와 forEach()를 써야할 때를 잘 구분해보는 걸 목표로...!

다른 풀이 1

function solution(score) {
  return score.map((el) => {
    return (
      score.filter((v) => (v[0] + v[1]) / 2 > (el[0] + el[1]) / 2).length + 1
    );
  });
}

아니 이게 이렇게 더 간단해질 줄이야 ㅠ

  1. score 배열을 map() 메서드를 통해 순회한다.
  2. score.filter((v) => (v[0] + v[1]) / 2 > (el[0] + el[1]) / 2) : score 배열에서 현재 학생의 평균 점수보다 높은 점수를 가진 학생들을 필터링한다.
  3. .length + 1 : 필터링 된 학생들 수에 1을 더하여 현재 학생의 등수를 계산한다.
  4. 이 과정을 score 배열의 각 요소에 대해 반복하여 각 ㅏㄱ생의 등수를 계산하고 그 결과를 새로운 배열에 담아 반환한다.

다른 풀이 2

function solution(score) {
    let avg = score.map(v=>(v[0]+v[1])/2);
    let sorted = avg.slice().sort((a,b)=>b-a);
    return avg.map(v=>sorted.indexOf(v)+1);
}
  1. 먼저 배열의 각 요소에 대해 평균 점수를 계산하여 avg 배열에 저장한다.
  2. avg.slice()를 통해 배열의 복사본을 만든 다음, 배열을 내림차순으로 정렬하여 sorted 배열에 저장한다.
  3. avg 배열의 각 요소(평균 점수)에 대해 sorted 배열에서 해당 값이 처음 등장하는 인덱스에 +1을 더하여 각 학생의 등수를 계산한다.
profile
영차영차 😎

0개의 댓글