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