Enumerable#max_by

Returns: Object · Added in v1.8.6 · Updated March 16, 2026 · Enumerable
ruby enumerable comparison maximum

The max_by method returns the element that would be largest according to the criteria you define in a block. Unlike max which compares elements directly, max_by lets you specify how to compare them.

How It Works

max_by evaluates the block for each element and returns the element that produced the largest value:

collection.max_by { |element| block_return_value }

The element itself is returned, not the block’s return value.

Basic Usage

Find the longest string in an array:

words = ["cat", "elephant", "dog", "hippopotamus"]
longest = words.max_by { |word| word.length }
# => "hippopotamus"

Find the oldest person in a collection:

people = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Charlie", age: 35 }
]

oldest = people.max_by { |person| person[:age] }
# => {:name=>"Charlie", :age=>35}

With Nested Comparisons

When multiple elements produce the same maximum value, max_by returns the first one encountered:

words = ["aa", "bb", "cc", "dd"]
result = words.max_by { |w| w[0] }
# => "aa" (all have the same value, first one wins)

Finding Multiple Maximum Elements

Use max_by with an argument to get multiple maximum elements:

numbers = [5, 2, 8, 1, 9, 3, 7, 4, 6]

largest_three = numbers.max_by(3) { |n| n }
# => [9, 8, 7]

This is useful for finding top performers by a specific metric:

products = [
  { name: "Laptop", price: 999 },
  { name: "Phone", price: 699 },
  { name: "Tablet", price: 449 },
  { name: "Watch", price: 299 },
  { name: "Headphones", price: 199 }
]

expensive_three = products.max_by(3) { |p| p[:price] }
# => [{:name=>"Laptop", :price=>999}, {:name=>"Phone", :price=>699}, {:name=>"Tablet", :price=>449}]

With Arrays of Arrays

pairs = [[1, 5], [3, 2], [2, 8], [4, 1]]

# Find pair with largest first element
by_first = pairs.max_by { |pair| pair[0] }
# => [3, 2]

# Find pair with largest second element
by_second = pairs.max_by { |pair| pair[1] }
# => [2, 8]

Practical Examples

Finding the Longest Method Name

methods = [:to_s, :inspect, :class, :object_id, :nil?]
longest = methods.max_by { |m| m.to_s.length }
# => :object_id (9 characters)

Finding the Fastest Shipping Option

shipping_options = [
  { carrier: "USPS", weight: 5, distance: 100 },
  { carrier: "FedEx", weight: 5, distance: 50 },
  { carrier: "UPS", weight: 5, distance: 75 }
]

fastest = shipping_options.max_by { |opt| 1.0 / (opt[:weight] * opt[:distance]) }
# => {:carrier=>"FedEx", :weight=>5, :distance=>50}

Finding the Furthest Location

current_location = { x: 10, y: 10 }

locations = [
  { name: "Office", x: 5, y: 5 },
  { name: "Home", x: 15, y: 15 },
  { name: "Store", x: 8, y: 12 }
]

furthest = locations.max_by { |loc| 
  (loc[:x] - current_location[:x]).abs + (loc[:y] - current_location[:y]).abs 
}
# => {:name=>"Home", :x=>15, :y=>15}

Comparison with max

MethodUse When
maxYou want natural/built-in comparison
max_byYou need custom comparison logic
numbers = [5, 2, 8, 1, 9]

numbers.max        # => 9 (natural comparison)
numbers.max_by { |n| n }  # => 9 (same result)

# With custom logic, max_by shines
numbers.max_by { |n| -n }  # => 1 (finds minimum via negative)

Performance Notes

  • max_by uses the spaceship operator (<=>) internally for comparisons
  • For enumerables that respond to #<=>, this is efficient
  • When no block is given, Ruby 3.0+ returns an enumerator
# Ruby 3.0+ - lazy evaluation
enum = [5, 2, 8, 1, 9].max_by
enum.each { |n| puts n }  # Still evaluates, but deferred

Return Value

Returns the element that maximizes the block’s return value, or nil if the collection is empty:

[].max_by { |x| x }  # => nil

With n argument, returns an array of n elements:

[3, 1, 4, 1, 5, 9, 2, 6].max_by(2)
# => [9, 6]

Edge Cases

Empty collections return nil:

[].max_by(&:to_s)  # => nil

Collections with one element return that element:

[42].max_by { |n| n }  # => 42

See Also