group_by와 partition
Coddy Ruby 여정의 로직 및 흐름 섹션에 포함된 레슨 — 56개 중 25번째.
가끔은 컬렉션을 필터링하는 대신 분할하고 싶을 때가 있습니다. 두 가지 메서드가 대부분의 경우를 해결해 줍니다.
group_by는 블록을 받아 해시를 반환합니다. 각 고유한 블록 결과는 키가 되며, 해당 결과를 생성한 요소들의 배열로 매핑됩니다:
words = ["hi", "hello", "yo", "hey", "bonjour"]
by_length = words.group_by { |w| w.length }
puts by_length.inspect
# {2=>["hi", "yo"], 5=>["hello"], 3=>["hey"], 7=>["bonjour"]}한 번의 순회로 항목들을 분류하는 가장 깔끔한 방법입니다.
partition은 이진(binary) 버전입니다. 이 메서드는 블록이 참이었던 요소들과 나머지 요소들로 구성된 한 쌍의 배열을 반환합니다:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]정확히 두 개의 버킷이 있을 때는 partition을, 여러 개가 있을 수 있을 때는 group_by를 사용하세요.
챌린지
중급쉼표로 구분된 name:score 항목 리스트(예: Alice:88,Bob:42,Charlie:75)를 읽습니다. group_by와 partition을 사용하여 간단한 보고서를 생성하세요.
단계:
- 각 항목을
[name, score]쌍으로 파싱합니다 (score는 정수형입니다). name의 첫 글자(대문자)를 기준으로group_by를 수행합니다.- 각 글자 그룹에 대해 알파벳 순서대로, 항목들을 합격(
score >= 60)과 불합격으로partition한 후, 그룹당 한 줄씩 출력합니다:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>각 그룹 내에서 이름은 원래 순서대로 나타나야 합니다. 한쪽에 이름이 없는 경우 비워둡니다 (예: fail=).
입력이 Alice:88,Adam:42,Bob:75,Beth:55,Cara:90인 경우, 출력은 다음과 같습니다:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=치트 시트
group_by는 컬렉션을 블록 결과에 따라 키가 지정된 해시로 나눕니다:
words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}partition은 정확히 두 개의 배열(일치하는 항목과 일치하지 않는 항목)로 나눕니다:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]두 개의 버킷에는 partition을 사용하고, 여러 개에는 group_by를 사용하세요.
직접 해보기
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# TODO: 첫 글자(대문자)로 그룹화하고, 각 그룹을 점수 60점 이상 여부로 분할한 뒤,
# 알파벳 순서대로 'X: pass=... fail=...' 형식으로 출력할 것
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
로직 및 흐름의 모든 레슨
5Enumerable의 강력한 기능
Select와 RejectMap 체이닝Reduce / Injectcount, all?, any?, none?group_by와 partitionsort_by, min_by, max_by요약 - 데이터 파이프라인