How to get the min and max from an Array (Ruby)

Arrays have a couple methods to get the minimum and maximum. Three common ones are .min, .max, .minmax.

.max will get you the maximum value.

[1,2,3].max
#=> 3

["a", "b", "c"].max
#=> "c"

.min will get the minimum value.

[1,2,3].min
#=> 1

["a", "b", "c"].min
#=> "a"

If you need both the minimum and the maximum from an array then the best solution is using the ruby method minmax. It will return the minimum and maximum values as an array like: [min, max].

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

["a", "b", "c", "d"].minmax 
#=> ["a", "d"]

You can also assign the minimum and maximum to variables like this:

a, b = [1, 2, 3, 4, 5, 6].minmax
a
#=> 1
b
#=> 6

y, z = ["a", "b", "c", "d"].minmax 
y
#=> "a"
z
#=> "d"

You can also get the min and max by sorting and getting the first or last value.

[5, 1, 3, 5, 6].sort.first
#=> 1

[8, 8, 2, 5, 7].sort.last
#=> 8 # Note that there are two 8s in the original array an only one 8 will be returned.

[3, 1, 45, 6, 3].sort[0]
#=> 1

[6, 7, 13, 30, 3].sort[-1]
#=> 30

If you were to define a custom method to get the min you could implement it like this:

class Array
  def monkey_patched_min
    self.sort.first
  end
end

[1, 2, 3, 4, 5].monkey_patched_min
#=> 1

By the way, don’t monkey patch code as a habit. Monkey patching is generally (but not always) a poor idea.

min, max and minmax are all defined on the Enumerable module so any class that includes Enumerable will be able to call those methods.

Some common errors you wil see are ArgumentError (comparison of Integer with nil failed) if you try to call .min, .max or .minmax on an array with nil in it.

[nil, 1, 2].min
#=> ArgumentError (comparison of Integer with nil failed)
# This fails.

[nil, 1, 2].max
#=> ArgumentError (comparison of Integer with nil failed)
# You might not expect this to fail since nil.to_i returns 0 
# and the max number in the array is 2. The failure isn't on 
# the 2 but because the comparison of of an Integer
# (1 or 2 in this case) with the nil object failed.

[nil, 1, 2].minmax
#=> ArgumentError (comparison of Integer with nil failed)
# This one also fails because of the comparison of an
# Integer with a nil object.

You can fix these errors by converting the nil to zero (make sure this is what you want to do).

[nil, 1, 2].map{|o| o.to_i}.min
#=> 0

[nil, 1, 2].map{|o| o.to_i}.max
#=> 2

[nil, 1, 2].map{|o| o.to_i}.minmax
#=> [0, 2]

[-2, -1, nil, 1, 2].map{|o| o.to_i}.minmax
#=> [-2, 2]

There is also an alternative way to write map so that it is shorter.

[-2, nil, 1, 2].map(&:to_i).minmax
#=> [-2, 2]

[-2, nil, 1, 2].map(&:to_i).min
#=> -2

[-2, nil, 1, 2].map(&:to_i).max
#=> 2

If you want to exclude the nil from the results returned by min, max or minmax you can use the reject method instead of converting the nil to a 0.

[-2, nil, 1, 2].reject{|o| o.nil?}.min
#=> -2

[nil, 1, 2].reject{|o| o.nil?}.min
#=> 1

[nil, 1, 2].reject{|o| o.nil?}.max
#=> 2

[nil, 1, 2].reject{|o| o.nil?}.minmax
#=> [1, 2]

These can also be written like:

[-2, nil, 1, 2].reject(&:nil?).min
#=> -2

[nil, 1, 2].reject(&:nil?).min
#=> 1

[nil, 1, 2].reject(&:nil?).max
#=> 2

[nil, 1, 2].reject(&:nil?).minmax
#=> [1, 2]

These methods also works with strings.

[nil, "a", "b"].map{|o| o.to_s}.minmax
#=> ["", "b"]

[nil, "a", "b"].map(&:to_s).minmax
#=> ["", "b"]

[nil, "a", "b", "c", "d"].reject(&:nil?).minmax
#=> ["a", "d"]

Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *