The .end of a Ruby range is the number used to specify the end of the range, whether or not the range is "exclusive of" the end. I don't understand the rationale for this design decision, but never the less, I was wondering what the most idiomatic mechanism is for determining the "effective end" of the range (i.e. greatest integer n such that range.include?(n) is true. The only mechanism I know of is last(1)[0], which seems pretty klunky.
Use the Range#max method:
r = 1...10
r.end
# => 10
r.max
# => 9
max won't work for exclusive ranges if any of the endpoints is Float (see range_max in range.c for details):
(1.0...10.0).max
# TypeError: cannot exclude non Integer end value
(1.0..10.0).max
# => 10.0
As an exception, if begin > end, no error is raised and nil is returned:
(2.0...1.0).max
# => nil
Update: max works in costant time for any inclusive range and exclusive ranges of integers, it returns the same value as end and end-1, respectively. It is also O(1) if for the range holds that begin > end, in this case nil is returned. For exlusive ranges of non integer objects (String, Date, ...) or when a block is passed, it calls Enumerable#max so it have to travel all the elements in the range!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With