Range 클래스
Range 클래스
Range 객체는 주어진 시작(begin) 값과 끝(end) 값 사이에 있는 값들의 모임을 나타내요. Array, 문자열 등 여러 타입의 연속 값을 나타내는 데 쓰여요.
출처: Ruby 4.0 API
본문
Range 만들기
리터럴로 만들 수 있어요. ..는 끝 값을 포함하고, ...는 끝 값을 제외해요.
# Ranges that use '..' to include the given end value.
(1..4).to_a # => [1, 2, 3, 4]
('a'..'d').to_a # => ["a", "b", "c", "d"]
# Ranges that use '...' to exclude the given end value.
(1...4).to_a # => [1, 2, 3]
('a'...'d').to_a # => ["a", "b", "c"]
Range.new 메서드로도 만들 수 있어요. 세 번째 인자 exclude_end로 끝 값을 제외하도록 정해요.
# Ranges that by default include the given end value.
Range.new(1, 4).to_a # => [1, 2, 3, 4]
Range.new('a', 'd').to_a # => ["a", "b", "c", "d"]
# Ranges that use third argument exclude_end to exclude the given end value.
Range.new(1, 4, true).to_a # => [1, 2, 3]
Range.new('a', 'd', true).to_a # => ["a", "b", "c"]
시작 없는 범위 (Beginless Ranges)
beginless range는 명확한 끝 값은 있지만 시작 값이 nil이에요. 그러한 범위는 끝 값까지 모든 값을 포함해요.
r = (..4) # => nil..4
r.begin # => nil
r.include?(-50) # => true
r.include?(4) # => true
r = (...4) # => nil...4
r.include?(4) # => false
Range.new(nil, 4) # => nil..4
Range.new(nil, 4, true) # => nil...4
시작 없는 범위로 배열을 슬라이스할 수도 있어요:
a = [1, 2, 3, 4]
# Include the third array element in the slice
r = (..2) # => nil..2
a[r] # => [1, 2, 3]
# Exclude the third array element from the slice
r = (...2) # => nil...2
a[r] # => [1, 2]
시작 없는 범위의 each 메서드는 예외를 발생시켜요.
끝 없는 범위 (Endless Ranges)
endless range는 명확한 시작 값은 있지만 끝 값이 nil이에요. 그러한 범위는 시작 값부터 모든 값을 포함해요.
r = (1..) # => 1..
r.end # => nil
r.include?(50) # => true
Range.new(1, nil) # => 1..
끝 없는 범위 리터럴은 두 점이나 세 점으로 쓸 수 있어요. 어느 쪽이든 같은 요소를 갖지만, 둘은 같지 않아요(not equal).
r0 = (1..) # => 1..
r1 = (1...) # => 1...
r0.begin == r1.begin # => true
r0.end == r1.end # => true
r0 == r1 # => false
끝 없는 범위로 배열을 슬라이스할 수도 있어요:
a = [1, 2, 3, 4]
r = (2..) # => 2..
a[r] # => [3, 4]
끝 없는 범위의 each 메서드는 주어진 블록을 무한히 호출해요:
a = []
r = (1..)
r.each do |i|
a.push(i) if i.even?
break if i > 10
end
a # => [2, 4, 6, 8, 10]
범위는 시작과 끝이 모두 없을 수도 있어요. 리터럴로 시작도 끝도 없는 범위를 쓸 때는 시작이나 끝 중 적어도 하나를 명시적 nil로 줘야 해요. Ruby가 Range#inspect에 쓰는 형태인, 명시적 nil 시작과 끝을 권장해요:
(nil..) # => (nil..nil)
(..nil) # => (nil..nil)
(nil..nil) # => (nil..nil)
Range와 다른 클래스 (Ranges and Other Classes)
객체의 클래스가 인스턴스 메서드 <=>를 구현하면 그 객체를 범위에 넣을 수 있어요. 그렇게 하는 Ruby 코어 클래스로 Array, Complex, File::Stat, Float, Integer, Kernel, Module, Numeric, Rational, String, Symbol, Time이 있어요.
t0 = Time.now # => 2021-09-19 09:22:48.4854986 -0500
t1 = Time.now # => 2021-09-19 09:22:56.0365079 -0500
t2 = Time.now # => 2021-09-19 09:23:08.5263283 -0500
(t0..t2).include?(t1) # => true
(t0..t1).include?(t2) # => false
범위의 요소들이 인스턴스 메서드 succ를 구현할 때만 범위를 반복(iterate)할 수 있어요. 그렇게 하는 Ruby 코어 클래스로 Integer, String, Symbol이 있어요(위에서 언급한 다른 클래스는 아님). 반복자 메서드에는 Range 자체의 each, step, %와, Enumerable 모듈에서 포함된 each_entry, each_with_index, each_with_object, each_slice, each_cons, reverse_each가 있어요.
a = []
(1..4).each {|i| a.push(i) }
a # => [1, 2, 3, 4]
Range와 사용자 정의 클래스 (Ranges and User-Defined Classes)
범위에 쓸 사용자 정의 클래스는 인스턴스 <=>를 구현해야 해요(Integer#<=> 참고). 반복을 가능하게 하려면 인스턴스 메서드 succ도 구현해야 해요(Integer#succ 참고). 아래 클래스는 <=>와 succ를 모두 구현해서, 범위를 만들고 반복하는 데 모두 쓸 수 있어요. Comparable 모듈이 포함되어 == 메서드가 <=>의 관점에서 정의된다는 점에 주의하세요.
# Represent a string of 'X' characters.
class Xs
include Comparable
attr_accessor :length
def initialize(n)
@length = n
end
def succ
Xs.new(@length + 1)
end
def <=>(other)
@length <=> other.length
end
def to_s
sprintf "%2d #{inspect}", @length
end
def inspect
'X' * @length
end
end
r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX
r.to_a #=> [XXX, XXXX, XXXXX, XXXXXX]
r.include?(Xs.new(5)) #=> true
r.include?(Xs.new(7)) #=> false
Public Class Methods
json_create(object)
as_json을 참고하세요. JSON에서 Range 객체를 복원해요.
new(begin, end, exclude_end = false) → new_range
주어진 begin과 end 객체를 기반으로 새 범위를 반환해요. 선택 인자 exclude_end는 객체 end를 범위의 마지막 객체로 포함할지 정해요:
Range.new(2, 5).to_a # => [2, 3, 4, 5]
Range.new(2, 5, true).to_a # => [2, 3, 4]
Range.new('a', 'd').to_a # => ["a", "b", "c", "d"]
Range.new('a', 'd', true).to_a # => ["a", "b", "c"]
Public Instance Methods
%(n) {|element| ... } → self
step과 같지만 n의 기본값은 제공하지 않아요. Enumerator::ArithmeticSequence를 더 간결하게 만들어주는 데 편리해요.
array = [0, 1, 2, 3, 4, 5, 6]
# slice each second element:
seq = (0..) % 2 #=> ((0..).%(2))
array[seq] #=> [0, 2, 4, 6]
# or just
array[(0..) % 2] #=> [0, 2, 4, 6]
이 경우 Ruby의 연산자 우선순위 때문에 범위 주위에 괄호가 필수라는 점을 주의하세요:
(0..7) % 2 #=> ((0..7).%(2)) -- as expected
0..7 % 2 #=> 0..1 -- parsed as 0..(7 % 2)
self == other → true or false
다음 조건을 모두 만족할 때만 true를 반환해요:
other가 range이다.other.begin == self.beginother.end == self.endother.exclude_end? == self.exclude_end?
그 외에는 false를 반환해요.
r = (1..5)
r == (1..5) # => true
r = Range.new(1, 5)
r == 'foo' # => false
r == (2..5) # => false
r == (1..4) # => false
r == (1...5) # => false
r == Range.new(1, 5, true) # => false
같은 인자라도 ==와 eql?의 반환값이 다를 수 있어요:
(1..2) == (1..2.0) # => true
(1..2).eql? (1..2.0) # => false
self === object → true or false
object가 self.begin과 self.end 사이에 있으면 true, 그렇지 않으면 false를 반환해요.
(1..4) === 2 # => true
(1..4) === 5 # => false
(1..4) === 'a' # => false
(1..4) === 4 # => true
(1...4) === 4 # => false
('a'..'d') === 'c' # => true
('a'..'d') === 'e' # => false
case 문은 메서드 ===를 사용해요:
case 79
when (1..50)
"low"
when (51..75)
"medium"
when (76..100)
"high"
end # => "high"
, ..`로 끝 없는 범위도 case 문에서 쓸 수 있어요:
case "2.6.5"
when ..."2.4"
"EOL"
when "2.4"..."2.5"
"maintenance"
when "2.5"..."3.0"
"stable"
when "3.1"..
"upcoming"
end # => "stable"
as_json(*)
Range#as_json과 Range.json_create 메서드는 Range 객체를 직렬화/역직렬화하는 데 쓸 수 있어요. Marshal을 참고하세요. Range#as_json은 self를 직렬화해서 2-요소 해시를 반환해요:
require 'json/add/range'
x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
JSON.create는 그런 해시를 역직렬화해서 Range 객체를 반환해요:
Range.json_create(x) # => 1..4
Range.json_create(y) # => 1...4
Range.json_create(z) # => "a".."d"
begin → object
self의 시작을 정의하는 객체를 반환해요. Range#first, Range#end와 관련돼요.
(1..4).begin # => 1
(..2).begin # => nil
bsearch {|obj| block } → value
이진 탐색(binary search)으로 self에서 요소를 선택해 반환해요. Binary Searching 섹션을 참고하세요.
count → integer
인자나 블록 기준(주어진 경우)에 따라 요소의 개수를 반환해요.
인자도 블록도 없으면 요소의 수를 반환해요:
(1..4).count # => 4
(1...4).count # => 3
('a'..'d').count # => 4
('a'...'d').count # => 3
(1..).count # => Infinity
(..4).count # => Infinity
인자 object가 주어지면 self에서 찾은 object의 수를 반환해요(보통 0 또는 1):
(1..4).count(2) # => 1
(1..4).count(5) # => 0
(1..4).count('a') # => 0
블록이 주어지면 각 요소로 블록을 호출하고, 블록이 truthy 값을 반환한 요소의 수를 반환해요:
(1..4).count {|element| element < 3 } # => 2
Range#size와 관련돼요.
cover?(object) → true or false / cover?(range) → true or false
주어진 인자가 self 안에 있으면 true, 그렇지 않으면 false를 반환해요.
범위가 아닌 인자 object는 <=와 <로 평가해요. 끝 값을 포함하는 범위(#exclude_end? == false)는 이렇게 평가해요:
self.begin <= object <= self.end
r = (1..4)
r.cover?(1) # => true
r.cover?(4) # => true
r.cover?(0) # => false
r.cover?(5) # => false
r.cover?('foo') # => false
r = ('a'..'d')
r.cover?('a') # => true
r.cover?('d') # => true
r.cover?(' ') # => false
r.cover?('e') # => false
r.cover?(0) # => false
끝 값을 제외하는 범위(#exclude_end? == true)는 이렇게 평가해요:
r.begin <= object < r.end
r = (1...4)
r.cover?(1) # => true
r.cover?(3) # => true
r.cover?(0) # => false
r.cover?(4) # => false
r.cover?('foo') # => false
r = ('a'...'d')
r.cover?('a') # => true
r.cover?('c') # => true
r.cover?(' ') # => false
r.cover?('d') # => false
r.cover?(0) # => false
범위 인자 range가 주어지면 self와 range의 첫 번째·마지막 요소를 비교해요:
r = (1..4)
r.cover?(1..4) # => true
r.cover?(0..4) # => false
r.cover?(1..5) # => false
r.cover?('a'..'d') # => false
r = (1...4)
r.cover?(1..3) # => true
r.cover?(1..4) # => false
시작과 끝이 숫자면 cover?는 include?처럼 동작해요. 하지만 숫자가 아니면 두 메서드는 다를 수 있어요:
(1..3).cover?(1.5) # => true
(1..3).include?(1.5) # => true
('a'..'d').cover?('cc') # => true
('a'..'d').include?('cc') # => false
다음 중 하나면 false를 반환해요: self의 시작 값이 끝 값보다 큰 경우, 또는 내부 <=> 호출이 nil을 반환해 비교할 수 없는 경우. Range#include?와 관련돼요.
시작 없는 범위는 끝 값 전까지 같은 타입의 모든 값을 덮어요(배타 범위는 끝 값을 제외). inclusive 범위일 때 시작 없는 범위의 끝에서 끝나는 범위, 또는 그보다 일찍 끝나는 범위를 덮어요.
(..2).cover?(1) # => true
(..2).cover?(2) # => true
(..2).cover?(3) # => false
(...2).cover?(2) # => false
(..2).cover?("2") # => false
(..2).cover?(..2) # => true
(..2).cover?(...2) # => true
(..2).cover?(.."2") # => false
(...2).cover?(..2) # => false
끝 없는 범위는 시작 이후 같은 타입의 모든 값을 덮어요. 끝 없는 배타(exclusive) 범위는 끝 없는 inclusive 범위를 덮지 않아요.
(2..).cover?(1) # => false
(2..).cover?(3) # => true
(2...).cover?(3) # => true
(2..).cover?(2) # => true
(2..).cover?("2") # => false
(2..).cover?(2..) # => true
(2..).cover?(2...) # => true
(2..).cover?("2"..) # => false
(2...).cover?(2..) # => false
(2...).cover?(3...) # => true
(2...).cover?(3..) # => false
(3..).cover?(2..) # => false
시작도 끝도 없는 범위는 모든 값·범위를 덮어 모든 인자에 true를 반환하지만, 시작도 끝도 없는 배타 범위는 끝 없는 inclusive 범위를 덮지 않아요:
(nil...).cover?(Object.new) # => true
(nil...).cover?(nil...) # => true
(nil..).cover?(nil...) # => true
(nil...).cover?(nil..) # => false
(nil...).cover?(1..) # => false
each {|element| ... } → self / each → an_enumerator
블록이 주어지면 self의 각 요소를 블록으로 전달해요. self.first.respond_to?(:succ)가 아니면 예외를 발생시켜요. 블록이 없으면 enumerator를 반환해요.
a = []
(1..4).each {|element| a.push(element) } # => 1..4
a # => [1, 2, 3, 4]
end → object
self의 끝을 정의하는 객체를 반환해요. Range#begin, Range#last와 관련돼요.
(1..4).end # => 4
(1...4).end # => 4
(1..).end # => nil
entries
to_a의 별칭이에요.
eql?(other) → true or false
다음 조건을 모두 만족할 때만 true를 반환해요:
other가 range이다.other.begin eql? self.beginother.end eql? self.endother.exclude_end? == self.exclude_end?
r = (1..5)
r.eql?(1..5) # => true
r = Range.new(1, 5)
r.eql?('foo') # => false
r.eql?(2..5) # => false
r.eql?(1..4) # => false
r.eql?(1...5) # => false
r.eql?(Range.new(1, 5, true)) # => false
exclude_end? → true or false
self가 자신의 끝 값을 제외하면 true, 아니면 false를 반환해요.
Range.new(2, 5).exclude_end? # => false
Range.new(2, 5, true).exclude_end? # => true
(2..5).exclude_end? # => false
(2...5).exclude_end? # => true
first → object / first(n) → array
인자 없이 호출하면 self의 첫 번째 요소를 반환해요(있을 때). 음이 아닌 정수 n이 주어지면 배열에서 첫 n개 요소를 반환해요. 첫 요소가 없으면 예외를 발생시켜요.
(1..4).first # => 1
('a'..'d').first # => "a"
(1..10).first(3) # => [1, 2, 3]
(1..10).first(0) # => []
(1..4).first(50) # => [1, 2, 3, 4]
(..4).first # Raises RangeError
hash → integer
self의 정수 해시 값을 반환해요. 두 range 객체 r0와 r1은 r0.eql?(r1)일 때만 같은 해시 값을 가져요. Range#eql?, Object#hash와 관련돼요.
include?(object) → true or false / member?
object가 self의 요소면 true, 아니면 false를 반환해요:
(1..4).include?(2) # => true
(1..4).include?(5) # => false
(1..4).include?(4) # => true
(1...4).include?(4) # => false
('a'..'d').include?('b') # => true
('a'..'d').include?('e') # => false
('a'..'d').include?('B') # => false
('a'..'d').include?('d') # => true
('a'...'d').include?('d') # => false
시작과 끝이 숫자면 include?는 cover?처럼 동작하지만, 숫자가 아니면 두 메서드는 다를 수 있어요.
member?는 include?의 별칭이에요.
inspect → string
begin.inspect와 end.inspect를 포함해 self의 문자열 표현을 반환해요:
(1..4).inspect # => "1..4"
(1...4).inspect # => "1...4"
(1..).inspect # => "1.."
(..4).inspect # => "..4"
to_s와 inspect의 반환은 다를 수 있어요:
('a'..'d').to_s # => "a..d"
('a'..'d').inspect # => "\"a\"..\"d\""
last → object / last(n) → array
인자 없이 호출하면 self의 마지막 요소를 반환해요(있을 때). exclude_end?가 true여도 인자 없이 last는 self의 끝 요소를 반환해요:
(1..4).last # => 4
('a'..'d').last # => "d"
(1...4).last # => 4
('a'...'d').last # => "d"
음이 아닌 정수 n이 주어지면 배열에서 마지막 n개 요소를 반환해요. exclude_end?가 true이면 인자와 함께 쓴 last는 끝 요소를 반환하지 않아요:
(1..10).last(3) # => [8, 9, 10]
(1..10).last(0) # => []
(1..4).last(50) # => [1, 2, 3, 4]
(1...4).last(3) # => [1, 2, 3]
('a'...'d').last(3) # => ["a", "b", "c"]
마지막 요소가 없으면 (1..).last처럼 예외를 발생시켜요.
max → object / max(n) → array / max {|a, b| ... } → object / max(n) {|a, b| ... } → array
메서드 <=> 또는 주어진 블록을 비교에 사용해 self의 최댓값을 반환해요. 인자도 블록도 없으면 self의 최대값 요소를 반환해요:
(1..4).max # => 4
('a'..'d').max # => "d"
(-4..-1).max # => -1
음이 아닌 정수 n이 주어지고 블록이 없으면, 배열에서 n개의 최대값 요소를 반환해요:
(1..4).max(2) # => [4, 3]
('a'..'d').max(2) # => ["d", "c"]
(-4..-1).max(2) # => [-1, -2]
(1..4).max(50) # => [4, 3, 2, 1]
블록이 주어지면 먼저 self의 처음 두 요소로, 그다음에는 지금까지의 최대값과 다음 요소로 순차적으로 호출돼요:
(1..4).max {|a, b| p [a, b]; a <=> b } # => 4
# Prints: [2, 1] / [3, 2] / [4, 3]
n이 0이면 빈 배열을 반환해요. 다음 중 하나면 nil이나 빈 배열을 반환해요: 시작 값이 끝 값보다 큰 경우((4..1).max # => nil), 배타 범위의 시작 값이 끝 값과 같은 경우((1...1).max # => nil). self가 endless 범위((1..))이거나, 블록이 주어졌는데 beginless 범위면 예외를 발생시켜요. Range#min, Range#minmax와 관련돼요.
min → object / min(n) → array / min {|a, b| ... } → object / min(n) {|a, b| ... } → array
메서드 <=> 또는 주어진 블록을 비교에 사용해 self의 최솟값을 반환해요. max와 대칭적으로 동작해요:
(1..4).min # => 1
('a'..'d').min # => "a"
(-4..-1).min # => -4
(1..4).min(2) # => [1, 2]
('a'..'d').min(2) # => ["a", "b"]
(-4..-1).min(2) # => [-4, -3]
(1..4).min(50) # => [1, 2, 3, 4]
n이 0이면 빈 배열을 반환해요. 시작 값이 끝 값보다 큰 경우나 배타 범위의 시작 값이 끝 값과 같은 경우 nil이나 빈 배열을 반환해요. self가 beginless 범위((..4))이거나, 블록이 주어졌는데 endless 범위면 예외를 발생시켜요. Range#max, Range#minmax와 관련돼요.
minmax → [object, object] / minmax {|a, b| ... } → [object, object]
비교 메서드 <=> 또는 주어진 블록에 따라 self의 최솟값과 최댓값을 담은 2-요소 배열을 반환해요.
(1..4).minmax # => [1, 4]
(1...4).minmax # => [1, 3]
('a'..'d').minmax # => ["a", "d"]
(-4..-1).minmax # => [-4, -1]
(1..4).minmax {|a, b| -(a <=> b) } # => [4, 1]
시작 값이 끝 값보다 큰 경우나 배타 범위의 시작 값이 끝 값과 같은 경우 [nil, nil]을 반환해요. self가 beginless 또는 endless 범위면 예외를 발생시켜요. Range#min, Range#max와 관련돼요.
overlap?(range) → true or false
range가 self와 겹치면 true, 아니면 false를 반환해요:
(0..2).overlap?(1..3) #=> true
(0..2).overlap?(3..4) #=> false
(0..).overlap?(..0) #=> true
범위가 아닌 인자에는 TypeError를 발생시켜요. 내부 <=> 호출이 nil을 반환하면 false를 반환해요:
(1..3).overlap?(1) # TypeError
(1..3).overlap?('a'..'d') # => false
self나 range가 비어 있으면 false를 반환해요. "빈 범위"란 시작 값이 끝 값보다 크거나(또는 exclusive 범위일 때 같거나) 한 경우를 뜻해요.
(4..1).overlap?(2..3) # => false
(2...2).overlap?(1..2) # => false
(1..2).overlap?(2...2) # => false
Range#cover?와 관련돼요. beginless 범위가 실제로 비어 있더라도(상한이 그 타입의 최솟값일 때) 그 결과는 참으로 보이는 경우가 있어요:
(...-Float::INFINITY).overlap?(...-Float::INFINITY) # => true
(..."").overlap?(..."") # => true
reverse_each {|element| ... } → self / reverse_each → an_enumerator
블록이 주어지면 self의 각 요소를 역순으로 블록으로 전달해요. 블록이 없으면 enumerator를 반환해요.
a = []
(1..4).reverse_each {|element| a.push(element) } # => 1..4
a # => [4, 3, 2, 1]
a = []
(1...4).reverse_each {|element| a.push(element) } # => 1...4
a # => [3, 2, 1]
size → non_negative_integer or Infinity or nil
시작과 끝 값이 모두 숫자면 self의 요소 수를 반환하고, 아니면 nil을 반환해요:
(1..4).size # => 4
(1...4).size # => 3
(1..).size # => Infinity
('a'..'z').size # => nil
self가 반복 가능(iterable)이 아니면 예외를 발생시켜요:
(0.5..2.5).size # TypeError
(..1).size # TypeError
Range#count와 관련돼요.
step(s = 1) {|element| ... } → self / step(s = 1) → enumerator
s 단계로 범위의 요소들을 반복해요. 반복은 + 연산자로 수행돼요. 블록이 주어지면 self의 각 요소를 단계만큼 건너뛰며 블록으로 전달해요:
(0..6).step(2) { puts _1 }
# Prints: 0, 2, 4, 6
# Iterate between two dates in step of 1 day (24 hours)
(Time.utc(2022, 2, 24)..Time.utc(2022, 3, 1)).step(24*60*60) { puts _1 }
# Prints:
# 2022-02-24 00:00:00 UTC
# 2022-02-25 00:00:00 UTC
# 2022-02-26 00:00:00 UTC
# 2022-02-27 00:00:00 UTC
# 2022-02-28 00:00:00 UTC
# 2022-03-01 00:00:00 UTC
+ step이 값을 줄이는 경우에도, 시작이 끝보다 높으면 반복은 여전히 수행돼요:
(0..6).step(-2) { puts _1 }
# Prints nothing
(6..0).step(-2) { puts _1 }
# Prints: 6, 4, 2, 0
(Time.utc(2022, 3, 1)..Time.utc(2022, 2, 24)).step(-24*60*60) { puts _1 }
# Prints 2022-03-01부터 하루씩 2022-02-24까지
블록이 주어지지 않고 범위 경계와 단계가 모두 Numeric이면 Enumerator::ArithmeticSequence를 반환해요:
(1..5).step(2) # => ((1..5).step(2))
(1.0..).step(1.5) #=> ((1.0..).step(1.5))
(..3r).step(1/3r) #=> ((..3/1).step((1/3)))
Enumerator::ArithmeticSequence는 컬렉션 반복이나 슬라이싱의 값 객체로 쓸 수 있어요(Array#[] 참고). step과 비슷하지만 더 간결하게 산술 시퀀스를 만드는 편의 메서드 %도 있어요:
# Same as (1..5).step(2)
(1..5) % 2 # => ((1..5).%(2))
일반적인 경우, 블록이 없으면 Enumerator를 반환해요:
('a'..).step('b') #=> #<Enumerator: "a"..:step("b")>
('a'..).step('b').take(3) #=> ["a", "ab", "abb"]
s가 주어지지 않으면 숫자 begin 범위에서는 1로 간주해요. 호환성(backward compatibility)을 위해 String 범위는 문자열 단계와 정수 단계 모두를 지원해요. 후자의 경우 String#succ로 다음 값을 계산해 반복해요:
(1..5).step { p _1 }
# Prints: 1, 2, 3, 4, 5
('a'..'e').step(2) { p _1 }
# Prints: a, c, e
to_a → array (entries의 원본)
self의 요소들을 배열로 반환해요. 유한한 컬렉션이 아니면 예외를 발생시켜요.
(1..4).to_a # => [1, 2, 3, 4]
(1...4).to_a # => [1, 2, 3]
('a'..'d').to_a # => ["a", "b", "c", "d"]
to_json(*args)
self를 나타내는 JSON 문자열을 반환해요:
require 'json/add/range'
puts (1..4).to_json
puts (1...4).to_json
puts ('a'..'d').to_json
# {"json_class":"Range","a":[1,4,false]}
# {"json_class":"Range","a":[1,4,true]}
# {"json_class":"Range","a":["a","d",false]}
to_s → string
begin.to_s와 end.to_s를 포함해 self의 문자열 표현을 반환해요. inspect와 다를 수 있어요.
(1..4).to_s # => "1..4"
(1...4).to_s # => "1...4"
(1..).to_s # => "1.."
(..4).to_s # => "..4"
to_set → set
self의 요소들을 담은 set을 반환해요. 유한한 컬렉션이 아니면 예외를 발생시켜요. require 'set'이 필요해요.
(1..4).to_set # => Set[1, 2, 3, 4]
(1...4).to_set # => Set[1, 2, 3]
(1..).to_set
# in 'Range#to_set': cannot convert endless range to a set (RangeError)