understanding ruby ranges
(0..3).to_a=>[0,1,2,3]
(0...3).to_a=>[0,1,2]
First will include the last element and second will exclude the last element..
Learn rubydoc for all references in ruby
Visit http://www.ruby-doc.org/core-1.9.3/Array.html for array..
Hope this helps
Meaning of Ruby === operator on Ranges
1..10
indicates a Range
from 0 to 10 in the mathematical sense and hence contains 3.14259
It is not the same as [1,2,3,4,5,6,7,8,9,10]
.
This array is a consequence of the method Range#each
, used by Enumerable#to_a
to construct the array representation of an object, yielding only the integer values included
in the Range, since yielding all real values would mean traversing an infinite number of elements.
Range exclusive of boundaries in ruby
You could also check the boundaries using first
and last
:
range_array.map{|a| a.include?(3660) && a.first != 3660 && a.last != 3660}.any?
Difference between '..' (double-dot) and '...' (triple-dot) in range generation?
The documentation for Range† says this:
Ranges constructed using
..
run from the beginning to the end inclusively. Those created using...
exclude the end value.
So a..b
is like a <= x <= b
, whereas a...b
is like a <= x < b
.
Note that, while to_a
on a Range of integers gives a collection of integers, a Range is not a set of values, but simply a pair of start/end values:
(1..5).include?(5) #=> true
(1...5).include?(5) #=> false
(1..4).include?(4.1) #=> false
(1...5).include?(4.1) #=> true
(1..4).to_a == (1...5).to_a #=> true
(1..4) == (1...5) #=> false
†The docs used to not include this, instead requiring reading the Pickaxe’s section on Ranges. Thanks to @MarkAmery (see below) for noting this update.
Difference between Range.include? and Range.member? in Ruby
They are aliases of each other. If you expand the source code in the docs you see they both refer to the same internal function.
Mapping a range in ruby
There is currently (Ruby 2.2.2) no better way than just
(range.begin.years.ago)..(range.end.years.ago)
If you look into the documentation of Range, you see that none of the methods directly implement something like that.
Then, there is the included module Enumerable
which already looses the range semantics (being defined by first and last element).
You could monkey-patch it yourself like:
class Range
def rmap(&b)
Range.new(yield(self.begin), yield(self.end), exclude_end?)
end
end
and then do (years.ago
requires ActiveSupport/Rails):
(1..5).rmap { | a | a.years.ago }
Obviously, the block has to yield values suitable for creating a range.
Ruby: Ranges or Sequences?
The confusion stems from the fact that Ruby has two types of ranges, which are treated somewhat differently: numeric ranges, having numeric objects as endpoints, and non-numeric ranges, having non-numeric objects as endpoints.
The doc for Range#include? states, "Returns true
if obj is an element of the range, false
otherwise. If begin and end are numeric, comparison is done according to the magnitude of the values.". Therefore,
(1..10).include? 2.17 #=> true
does not mean that 2.17
is an element of the range, merely that 2.17.between?(1, 10) #=> true
.
You have a point that the first sentence of the doc is inaccurate--or at best misleading--for numeric ranges. After all, if we write
(1..10).any? { |n| n == 2.17 } #=> false
what does it mean that 2.17
is "an element of the range"? That is not an issue for non-numeric ranges.
I think the doc for Range#include?
should be more precise. Firstly, after having earlier defined numeric and non-numeric ranges, it would be helpful to define the concept of a member or element of a non-numeric range: "For a non-numeric range r
, obj
is a member of r
if and only if r.any? { |o| o == obj } #=> true
. I see no reason to attempt a definition of member for numeric ranges.
Range#include?
might then be documented as follows: "A numeric range r
returns true
if r.begin <= obj <= r.end
for two-dot ranges and r.begin <= obj < r.end
for three-dot ranges; else returns false
. A non-numeric range returns true
if obj
is a member of the range; else false
."
Open ranges in Ruby using floats?
you can exclude rightmost element of the range with ...
. See example below
(1..10).to_a # an array of numbers from 1 to 10 - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(1...10).to_a # an array of numbers from 1 to 9 - [1, 2, 3, 4, 5, 6, 7, 8, 9]
Ruby range: operators in case statement
It should just work like you said. The below case
construct includes the value 500.
case my_number
# between 100 and 500
when 100..500
puts "Correct, do something"
end
So:
case 500
when 100..500
puts "Yep"
end
will return Yep
Or would you like to perform a separate action if the value is exactly 500?
Related Topics
Can You Install Documentation for Existing Gems
Set Locale Automatically in Ruby on Rails
How to Make Like Clause Case-Insensitive
Installing Ruby-2.1.2: Cannot Load Such File -- Openssl (Loaderror)
Ruby on Rails: Confirmation Page for Activerecord Object Creation
Dynamic Active Record Store Accessors Based Off a User Form
Rails Server Cannot Start; Getaddrinfo: Nodename Nor Servname Provided, or Not Known (Socketerror)
How to Strip Leading and Trailing Quote from String, in Ruby
Ruby: Building a Plot of Function
Difference Between or and || When Setting Variables
Ruby Converting String Encoding from Iso-8859-1 to Utf-8 Not Working
Integrating @Font-Face Files into Rails Asset Pipeline