범위는 두 값 사이의 구간을 나타내요.
범위를 지원하는 가장 흔한 타입은 Integer와 String이에요.
범위는 컬렉션을 빠르게 만들기, 문자열 자르기, 값이 범위 안에 있는지 확인하기, 반복하기 등 여러 가지 일에 쓸 수 있어요.
범위는 범위 연산자 .. 또는 ...로 만들어요 (각각 끝 값을 포함하는 범위와 포함하지 않는 범위예요).
1..5 # => 1..5
1...5 # => 1...5
(1..5).to_a # => [1, 2, 3, 4, 5]
(1...5).to_a # => [1, 2, 3, 4]
범위 연산자가 두 개 있는 이유는 끝 값을 포함하거나 포함하지 않는 범위를 만들 수 있게 하기 위해서예요. 예를 들어 0부터 시작하는 인덱스를 다룰 때 유용해요.
Range 생성자로도 범위를 만들 수 있어요.
Range.new(1, 5) # A range containing 1, 2, 3, 4, 5
Ruby에서 범위 연산자 ..나 ...로 범위를 만들고, 그 범위에 메서드를 호출하고 싶을 때는 범위를 괄호로 감싸야 해요.
그러지 않으면 메서드가 범위 연산자의 두 번째 인자에 호출되기 때문이에요.
(1..5).sum # => 15
1..5.sum # => Error: undefined method `sum' for 5:Integer (NoMethodError)
문자열을 자르고 싶을 때는 범위 연산자로 부분 문자열을 얻을 수 있어요. 즉, 부분 문자열의 시작 인덱스와 끝 인덱스로 범위를 만드는 거예요.
"Hello World"[0..4] # => "Hello"
"Hello World"[6..10] # => "World"
음수 인덱스를 써서 문자열 끝에서부터 부분 문자열을 얻을 수도 있어요.
"Hello World"[-5..-1] # => "World"
"Hello World"[6..-4] # => "Wo"
범위에는 범위를 다룰 때 쓸 수 있는 메서드들이 있어요. 예를 들어, 이런 메서드로 범위에 있는 모든 값의 합을 구하거나 범위에 어떤 값이 포함되는지 확인할 수 있어요.
| 메서드 | 설명 | 예시 |
|---|---|---|
sum |
범위에 있는 모든 값의 합을 반환해요 | (1..5).sum # => 15 |
size |
범위의 크기를 반환해요 | (1..5).size # => 5 |
include? |
범위에 주어진 값이 포함되면 true를, 그렇지 않으면 false를 반환해요 |
(1..5).include?(3) # => true |
범위는 끝이 없거나 시작이 없을 수 있어요.
끝이 없거나 시작이 없는 범위는 시작값이나 끝값이 nil이지만, 범위를 정의할 때 nil은 생략할 수 있어요.
시작이 없거나 끝이 없는 범위는 예를 들어 문자열을 처음부터 자르거나 끝까지 자르고 싶을 때 유용해요.
"Hello World"[0..] # => "Hello World"
"Hello World"[4..] # => "o World"
"Hello World"[..5] # => "Hello "
컬렉션에 쓰지 않으면 끝이 없는 범위는 자칫 끝없이 이어지는 나열을 만들 수 있으니 주의해야 해요.
문자열도 범위에 쓸 수 있고, 두 문자열 사이의 문자열 구간을 얻을 수 있어요. 특정 문자열을 쓰면 동작이 조금 예상 밖일 수 있으니 주의해서 사용해요.
"aa".."az".to_a # => ["aa", "ab", "ac", ..., "az"]
Ruby에서는 범위에 사용자 정의 객체를 쓸 수 있어요. 그러려면 객체가 다음을 구현해야 해요:
Comparable 모듈을 포함succ 메서드<=> 메서드이 메서드들이 있어야 범위가 객체를 반복하고 범위 안의 객체를 비교할 수 있어요.
class Foo
include Comparable
attr_reader :value
def initialize(value)
@value = value
end
def succ
Foo.new(value + 1)
end
def <=>(other)
value <=> other.value
end
end
(Foo.new(1)..Foo.new(5))
# => #<Foo:0x7f3552bebe70 @value=1>, #<Foo:0x7f3552bebe50 @value=2>, #<Foo:0x7f3552bebe40 @value=3>, #<Foo:0x7f3552bebe30 @value=4>, #<Foo:0x7f3552bebe20 @value=5>