범위

범위 에서 Ruby

1개의 연습 문제

범위 소개

범위는 두 값 사이의 구간을 나타내요. 범위를 지원하는 가장 흔한 타입은 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
Note

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

컬렉션에 쓰지 않으면 끝이 없는 범위는 자칫 끝없이 이어지는 나열을 만들 수 있으니 주의해야 해요.

문자열 범위

문자열도 범위에 쓸 수 있고, 두 문자열 사이의 문자열 구간을 얻을 수 있어요. 특정 문자열을 쓰면 동작이 조금 예상 밖일 수 있으니 주의해서 사용해요.

"aa".."az".to_a # => ["aa", "ab", "ac", ..., "az"]

범위에 사용자 정의 객체 사용하기

Advanced

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>
GitHub에서 편집 링크가 새 창이나 탭에서 열려요

범위 배우기