Enumerable#min_by

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

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

How It Works

min_by evaluates the block for each element and returns the element that produced the smallest value:

collection.min_by { |element| block_return_value }

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

Basic Usage

Find the shortest string in an array:

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

Find the youngest person in a collection:

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

youngest = people.min_by { |person| person[:age] }
# => {:name=>"Bob", :age=>25}

With Nested Comparisons

When multiple elements produce the same minimum value, min_by returns the first one encountered:

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

Finding Multiple Minimum Elements

Use min_by with an argument to get multiple minimum elements:

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

smallest_three = numbers.min_by(3) { |n| n }
# => [1, 2, 3]

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 }
]

cheapest_three = products.min_by(3) { |p| p[:price] }
# => [{:name=>"Headphones", :price=>199}, {:name=>"Watch", :price=>299}, {:name=>"Tablet", :price=>449}]

With Arrays of Arrays

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

# Find pair with smallest first element
by_first = pairs.min_by { |pair| pair[0] }
# => [1, 5]

# Find pair with smallest second element
by_second = pairs.min_by { |pair| pair[1] }
# => [4, 1]

Practical Examples

Finding the Shortest Method Name

methods = [:to_s, :inspect, :class, :object_id, :nil?]
shortest = methods.min_by { |m| m.to_s.length }
# => :nil? (4 characters)

Finding the Cheapest Shipping Option

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

cheapest = shipping_options.min_by { |opt| opt[:weight] * opt[:distance] * 0.5 }
# => {:carrier=>"FedEx", :weight=>5, :distance=>50}

Finding the Nearest 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 }
]

nearest = locations.min_by { |loc| 
  (loc[:x] - current_location[:x]).abs + (loc[:y] - current_location[:y]).abs 
}
# => {:name=>"Office", :x=>5, :y=>5}

Comparison with min

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

numbers.min        # => 1 (natural comparison)
numbers.min_by { |n| n }  # => 1 (same result)

# With custom logic, min_by shines
numbers.min_by { |n| -n }  # => 9 (finds maximum via negative)

Performance Notes

  • min_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].min_by
enum.each { |n| puts n }  # Still evaluates, but deferred

Return Value

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

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

With n argument, returns an array of n elements:

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

Edge Cases

Empty collections return nil:

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

Collections with one element return that element:

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

See Also