트랙
/
jq
jq
/
연습 문제
/
성적 통계
성적 통계

성적 통계

학습 연습 문제

소개

Reduce

숫자 배열의 합을 구하고 싶다고 해봐요. 이 목표를 이루는 방법은 여러 가지가 있어요.

  • 여러 언어에서는 이 문제를 누산기 변수를 사용한 루프로 표현해요.

  • 이 문제는 재귀 함수로 작성할 수도 있어요. 의사 코드로 나타내면 다음과 같아요.

    function Add(X, Sum=0):
      if X is empty then
        return Sum
      else
        return Add(rest(X), Sum + first(X))
      end
    end
    

    문제를 더 작은 조각으로 나누는 이 방법은 "기저 사례를 향해 줄여 나가기"라고 표현할 수도 있어요.

Reduce는 데이터 구조의 모든 원소를 하나의 값으로 결합하는 방법이에요. 이 과정은 데이터 구조를 반복하면서 각 원소에 함수를 적용해 누적된 결과를 갱신해요.

jq에서는 이 과정이 reduce 필터로 구현되어 있어요. 다른 언어에서는 "fold", "fold-left", "inject", "aggregate"라고 부르기도 해요.

jq의 reduce 표현식은 다음과 같아요.

reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
  • STREAM_EXPRESSION은 항목의 _스트림_이고, 각 항목은 차례로 $var 변수에 저장돼요.
    • 배열을 스트림으로 만들려면 반복자 필터 .[]를 사용한다는 걸 기억해요: $myArray | .[].
  • INITIAL_VALUE는 누적된 결과의 시작 값이에요("누산기"라고도 해요).
  • UPDATE_EXPRESSION은 현재 값($var)을 누산기에 결합("fold")해요.
    • 이 표현식에서 .은 누산기의 값이에요.
    • 표현식의 출력은 다음 반복에서 사용하도록 누산기에 저장돼요.
    • 마지막 반복이 끝나면 누적된 결과가 reduce의 출력이에요.

예를 하나 살펴봐요: 배열에 있는 숫자들을 모두 더하는 거예요. add 필터가 바로 이 일을 하지만, 이걸 어떻게 구현하는지 살펴볼게요.

[10, 20, 30, 40]을 입력으로 사용하고 0을 초기 상태로 두면, 각 단계는 다음과 같아요.

# 상태 원소 리듀서 결과
1 0 10 0 + 10 10
2 10 20 10 + 20 30
3 30 30 30 + 30 60
4 60 40 60 + 40 100

jq 문법으로 나타내면 이런 코드가 돼요.

0 + 10 | . + 20 | . + 30 | . + 40

이걸 reduce 필터로 표현할 수 있어요.

[10, 20, 30, 40] | reduce .[] as $n (0; . + $n)     # => 100
Note

add 내장 함수는 사실 reduce로 구현되어 있지만, 초기 상태로 "null"을 사용해요(어떤 데이터 타입이든 null에 더할 수 있어요).

def add: reduce .[] as $x (null; . + $x);

몇 가지 기억할 점

  • 리듀싱 표현식에서 .은 누산기예요. 리듀싱 함수 안에서 참조해야 하는 객체가 입력으로 들어온다면, 그 객체를 변수에 저장해야 해요.

    {"apple": 10, "banana": 16, "carrot": 4}
    | . as $obj
    | reduce (keys | .[]) as $key (0; . + $obj[$key])     # => 30
    
  • 누산기는 어떤 데이터 타입이든 될 수 있어요. 예를 들어 배열을 뒤집고 싶을 수도 있어요.

    ["A", "B", "C", "D"]
    | reduce .[] as $elem ([]; [$elem] + .)       # => ["D", "C", "B", "A"]
    

지침

선생님이에요. 학년 말이 되면 학생마다 숫자로 성적을 매겨 두었어요. 이제 그 성적을 알파벳 등급으로 바꾸고, 각 등급을 받은 학생이 몇 명인지 세어야 해요.

1. 숫자 성적을 알파벳 등급으로 바꾸기

letter_grade 함수는 숫자 성적을 입력으로 받아서 해당 등급 문자를 출력해요. 다음 범위를 사용해요:

등급 점수
A 90% - 100%
B 80% - 89%
C 70% - 79%
D 60% - 69%
F 0% - 59%

예시:

75 | letter_grade   # => "C"

2. 등급별 학생 수 세기

count_letter_grades 함수는 학생 이름을 성적에 매핑한 객체를 입력으로 받아요. 출력은 각 등급을 그 등급을 받은 학생 수에 매핑한 객체예요.

예시:

{"Joe": 78, "Jane": 93, "Richard": 72} | count_letter_grades
# => {"A": 1, "B": 0, "C": 2, "D": 0, "F": 0}

이 문제를 푸는 방법은 여러 가지가 있어요. 연습 삼아 reduce 필터를 사용해 봐요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
jq Exercism

성적 통계 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 jq 트랙을 개념 12개연습 문제 75개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.