group_by builds a hash where each key points to matching values.

group by `group_by` chooses a key for each item and collects items with the same key.

Group By Intro

split_at
group_by_intro.rb
Replay: real traced execution (multi-file project)
split_at = 5
numbers = [2, 4, 5, 8]

groups = numbers.group_by do |number|
  number >= split_at ? "large" : "small"
end

small = groups.fetch("small", [])
large = groups.fetch("large", [])

puts "split_at=#{split_at}"
puts "small=#{small.join(",")}"
puts "large=#{large.join(",")}"
split_at = 4
numbers = [2, 4, 5, 8]

groups = numbers.group_by do |number|
  number >= split_at ? "large" : "small"
end

small = groups.fetch("small", [])
large = groups.fetch("large", [])

puts "split_at=#{split_at}"
puts "small=#{small.join(",")}"
puts "large=#{large.join(",")}"
split_at = 7
numbers = [2, 4, 5, 8]

groups = numbers.group_by do |number|
  number >= split_at ? "large" : "small"
end

small = groups.fetch("small", [])
large = groups.fetch("large", [])

puts "split_at=#{split_at}"
puts "small=#{small.join(",")}"
puts "large=#{large.join(",")}"
  1. split_at ← 5, numbers ← [2, 4, 5, 8]

    1split_at→ 5 = 5  #@split_at=4, 72numbers→ [2, 4, 5, 8] = [2, 4, 5, 8]34groups = numbers[2, 4, 5, 8].group_by do |number|5  number >= split_at ? "large" : "small"6end
  2. do |number|

    pass 1 of 4
    4groups = numbers.group_by do |number2|5  number >= split_at ? "large" : "small"6end
    All 4 passes — pass 1 is the card above
    passnumbernumbersgroups
    12
    24
    35
    48[2, 4, 5, 8]{"small"=>[2, 4], "large"=>[5, 8]}
  3. small ← [2, 4], large ← [5, 8]

    8small→ [2, 4] = groups.fetch("small", [])[2, 4]9large→ [5, 8] = groups.fetch("large", [])[5, 8]1011puts "split_at=#{split_at5}"12puts "small=#{small.join(",")2,4}"13puts "large=#{large.join(",")5,8}"
    outputsplit_at=5
    small=2,4
    large=5,8
  1. split_at ← 4, numbers ← [2, 4, 5, 8]

    1split_at→ 4 = 42numbers→ [2, 4, 5, 8] = [2, 4, 5, 8]34groups = numbers[2, 4, 5, 8].group_by do |number|5  number >= split_at ? "large" : "small"6end
  2. do |number|

    pass 1 of 4
    4groups = numbers.group_by do |number2|5  number >= split_at ? "large" : "small"6end
    All 4 passes — pass 1 is the card above
    passnumbernumbersgroups
    12
    24
    35
    48[2, 4, 5, 8]{"small"=>[2], "large"=>[4, 5, 8]}
  3. small ← [2], large ← [4, 5, 8]

    8small→ [2] = groups.fetch("small", [])[2]9large→ [4, 5, 8] = groups.fetch("large", [])[4, 5, 8]1011puts "split_at=#{split_at4}"12puts "small=#{small.join(",")2}"13puts "large=#{large.join(",")4,5,8}"
    outputsplit_at=4
    small=2
    large=4,5,8
  1. split_at ← 7, numbers ← [2, 4, 5, 8]

    1split_at→ 7 = 72numbers→ [2, 4, 5, 8] = [2, 4, 5, 8]34groups = numbers[2, 4, 5, 8].group_by do |number|5  number >= split_at ? "large" : "small"6end
  2. do |number|

    pass 1 of 4
    4groups = numbers.group_by do |number2|5  number >= split_at ? "large" : "small"6end
    All 4 passes — pass 1 is the card above
    passnumbernumbersgroups
    12
    24
    35
    48[2, 4, 5, 8]{"small"=>[2, 4, 5], "large"=>[8]}
  3. small ← [2, 4, 5], large ← [8]

    8small→ [2, 4, 5] = groups.fetch("small", [])[2, 4, 5]9large→ [8] = groups.fetch("large", [])[8]1011puts "split_at=#{split_at7}"12puts "small=#{small.join(",")2,4,5}"13puts "large=#{large.join(",")8}"
    outputsplit_at=7
    small=2,4,5
    large=8

Build the Buckets

  1. Start with numbers: [2, 4, 5, 8].
  2. The block chooses "small" or "large" for each number.
  3. group_by puts numbers with the same key together.
  4. fetch reads each bucket and uses an empty array if it is missing. | Number | Key when split_at is 5 | | --- | --- | | 2 | small | | 4 | small | | 5 | large | | 8 | large |

Exercise: group_by_intro.rb

Group numbers into small and large buckets, then print each bucket with an empty fallback