rubyguides

Enumerable#min

The min method returns the smallest element in an enumerable collection. It compares elements using the <=> operator (spaceship operator) to determine order.

That makes it a good match when the natural order of the elements already reflects the answer you want. For numbers, strings, and custom objects with a sensible comparison method, min gives you a direct way to ask for the lowest value.

The method also reads well when the collection is already sorted by the thing you care about. In that case, the call is short, the intent is clear, and the return value is easy to explain to another reader.

Basic Usage

Without arguments, min returns the single smallest element:

[3, 1, 4, 1, 5, 9, 2, 6].min
# => 1

["banana", "apple", "cherry"].min
# => "apple"

Passing an integer to min returns that many of the smallest entries as an array. This is useful for finding the bottom N scores, the cheapest items, or the earliest entries in a sorted list.

getting the n smallest elements

Pass an integer n to get the n smallest elements as an array:

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

["banana", "apple", "cherry", "date"].min(2)
# => ["apple", "banana"]

This form is useful when you want a short ranked list instead of a single answer. It keeps the comparison logic inside Ruby while still returning a plain array that you can print, slice, or pass along.

custom comparison with a block

You can provide a block to define custom comparison logic:

[-5, 3, -1, 7, -2].min { |a, b| a.abs <=> b.abs }
# => -1

["hello", "world", "ruby"].min { |a, b| a.length <=> b.length }
# => "ruby"

The block must return -1, 0, or 1 (using the spaceship operator convention).

If you need to compare by a derived property instead of the element itself, keep the block small and focused. That way the meaning of “smallest” stays visible at the call site.

That rule keeps the code honest. The call site should explain the decision, while the block should stay small enough that the comparison is easy to review later.

handling empty collections

min returns nil when called on an empty collection:

[].min
# => nil

[].min(2)
# => []

An empty collection is a useful edge case because it shows that min does not invent a value. Instead, it gives you nil for the single-value form and an empty array for the n-value form.

min vs min_by

These two methods are often confused but behave differently:

MethodWhat it compares
minCompares elements by their actual value using <=>
min_byCompares elements by the result of the block
# min compares by value
[1, 2, 3].min
# => 1

# min_by compares by block result
["one", "two", "three"].min_by { |s| s.length }
# => "one"

Practical Examples

The comparison block follows the same spaceship convention: return -1, 0, or 1 to indicate ordering. When comparing by a single field like price or length, min_by is often clearer because it names the attribute directly instead of spelling out a pairwise rule.

finding the lowest price

products = [
  { name: "Widget", price: 29.99 },
  { name: "Gadget", price: 49.99 },
  { name: "Doohickey", price: 19.99 }
]

cheapest = products.min { |a, b| a[:price] <=> b[:price] }
cheapest[:name]
# => "Doohickey"

When the comparison needs to follow a rule other than the default order, the block form lets you define the meaning of “smallest” at the call site. For strings, this might mean shortest length rather than first alphabetically.

When the comparison needs to follow a rule other than the default order, the block form lets you define the meaning of smallest at the call site. For strings, this might mean shortest length rather than first alphabetically.

finding the smallest string

words = ["elephant", "cat", "giraffe", "ant"]

shortest = words.min { |a, b| a.length <=> b.length }
# => "cat"

For ranked lists, asking for the n cheapest items returns a sorted array of the smallest entries by the comparison you specify. This works well with structured data where the comparison targets a numeric field.

For ranked lists, asking for the cheapest N items returns a sorted array of the smallest entries by the comparison you specify. This works well with structured data where the comparison targets a numeric field.

getting the n cheapest items

products = [
  { name: "Widget", price: 29.99 },
  { name: "Gadget", price: 49.99 },
  { name: "Doohickey", price: 19.99 },
  { name: "Thingamajig", price: 39.99 }
]

products.min(2) { |a, b| a[:price] <=> b[:price] }
# => [{:name=>"Doohickey", :price=>19.99}, {:name=>"Widget", :price=>29.99}]

Domain objects that implement the spaceship operator let min compare instances without a block. The class defines what “smallest” means, and min follows that rule for every call.

Domain objects that implement the spaceship operator let min compare instances without a block. The class defines what smallest means, and min follows that rule for every call.

working with custom objects

class Player
  attr_reader :score

  def initialize(name, score)
    @name = name
    @score = score
  end

  def <=>(other)
    @score <=> other.score
  end

  def to_s
    @name
  end
end

players = [
  Player.new("Alice", 95),
  Player.new("Bob", 87),
  Player.new("Charlie", 92)
]

players.min
# => Bob (score: 87)

When a class provides its own <=> method, min returns the lowest-ranked instance using that definition. For performance-sensitive code, min_by may be a better choice because it evaluates the block once per element instead of recomparing during a sort-like pass.

When a class provides its own spaceship method, min returns the lowest-ranked instance using that definition. For performance-sensitive code, min_by may be a better choice because it evaluates the block once per element instead of recomparing during a sort-like pass.

Performance Notes

min uses the <=> operator to compare elements. For arrays, it performs a single pass through the collection — O(n) time complexity.

When using min with a block, the comparison logic runs multiple times during the sort. For finding a single minimum, min_by is often more efficient since it only evaluates the block once per element.

In practice, min shines when the collection already implements the comparison you need. If you are choosing by score, length, or price, min_by often reads more clearly because the block spells out the rule in one place.

See Also