RbRuby · Lesson 5 of 11

Arrays, Hashes & Ranges

Ruby's collection classes are loaded with useful methods. You'll rarely need to write a loop — there's almost always a method for what you're trying to do.

Ruby
# Arrays
fruits = ["apple", "banana", "cherry"]
puts fruits[0]      # apple
puts fruits[-1]     # cherry (negative index)
puts fruits[1..2]   # ["banana", "cherry"] (range slice)

# Mutating
fruits.push("date")        # add to end
fruits << "elderberry"     # same, << is the append operator
fruits.unshift("avocado")  # add to start
fruits.pop                 # remove from end
fruits.shift               # remove from start

# Enumerable methods — the real power
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

puts nums.sort.inspect          # [1, 1, 2, 3, 3, 4, 5, 5, 6, 9]
puts nums.uniq.inspect          # [3, 1, 4, 5, 9, 2, 6]
puts nums.min                   # 1
puts nums.max                   # 9
puts nums.sum                   # 39
puts nums.count                 # 10
puts nums.count(5)              # 2 (how many 5s)

# map / select / reject / reduce
doubled  = nums.map    { |n| n * 2 }
evens    = nums.select { |n| n.even? }
odds     = nums.reject { |n| n.even? }
total    = nums.reduce(:+)        # 39 (shorthand for sum)
product  = nums.reduce(1, :*)    # product of all

# find / all? / any? / none?
puts nums.find   { |n| n > 4 }      # 5 (first match)
puts nums.all?   { |n| n > 0 }      # true
puts nums.any?   { |n| n > 8 }      # true
puts nums.none?  { |n| n > 10 }     # true
Ruby
# Hashes — key/value pairs
person = {
  name: "Alice",      # symbol keys (common)
  age: 30,
  city: "Paris"
}

puts person[:name]           # Alice
puts person.fetch(:country, "Unknown")   # Unknown (safe default)

# Mutating
person[:email] = "alice@example.com"
person.delete(:city)

# Iterating
person.each do |key, value|
  puts "#{key}: #{value}"
end

# Transformation
person.map { |k, v| [k, v.to_s.upcase] }.to_h
person.select { |k, v| v.is_a?(String) }
person.any?   { |k, v| v == 30 }

# Useful methods
puts person.keys.inspect       # [:name, :age, :email]
puts person.values.inspect     # ["Alice", 30, "alice@..."]
puts person.key?(:name)        # true
puts person.merge(active: true).inspect  # non-destructive merge

# Ranges
r = (1..10)          # inclusive (1 to 10)
r2 = (1...10)        # exclusive (1 to 9)

puts r.include?(5)   # true
puts r.to_a.inspect  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
puts r.sum           # 55
puts r.min           # 1
puts ('a'..'e').to_a.inspect  # ["a", "b", "c", "d", "e"]
✦ Tip
`map` returns a new array. `each` returns the original. `select` keeps matches. `reject` drops matches. `reduce` collapses to a single value. When in doubt: if you need a new array, use `map` or `select`. If you just want a side effect (printing, writing), use `each`.