범위와 진행(Ranges and progressions)
범위와 진행(Ranges and progressions)
범위(Range)와 진행(Progression)은 Kotlin에서 값들의 수열을 정의하는 도구예요. 범위 연산자, 반복, 사용자 정의 step, 산술 진행을 지원합니다.
출처: Kotlin 공식 문서
본문
범위(Ranges)
Kotlin에서는 kotlin.ranges 패키지의 .rangeTo()와 .rangeUntil() 함수로 값의 범위를 쉽게 만들 수 있어요. 범위는 시작과 끝이 정해진 값들의 순서 있는 집합을 의미하고, 기본적으로는 각 단계마다 1씩 증가해요. 예를 들어 1..4는 1, 2, 3, 4를 나타냅니다.
- 닫힌 범위(closed-ended range) 를 만들려면
..연산자로.rangeTo()를 호출해요. 시작 값과 끝 값이 모두 포함되죠. - 열린 범위(open-ended range) 를 만들려면
..<연산자로.rangeUntil()을 호출해요. 시작 값은 포함하지만 끝 값은 제외됩니다.
예를 들어 볼게요:
fun main() {
//sampleStart
// Closed-ended range: includes both 1 and 4
println(4 in 1..4)
// true
// Open-ended range: includes 1, excludes 4
println(4 in 1..<4)
// false
//sampleEnd
}
범위는 for 루프에서 반복할 때 특히 유용해요:
fun main() {
//sampleStart
for (i in 1..4) print(i)
// 1234
//sampleEnd
}
숫자를 역순으로 반복하려면 .. 대신 downTo 함수를 사용해요:
fun main() {
//sampleStart
for (i in 4 downTo 1) print(i)
// 4321
//sampleEnd
}
기본 증가값인 1 대신 사용자 정의 step으로 반복할 수도 있어요. step() 함수를 쓰면 됩니다:
fun main() {
//sampleStart
for (i in 0..8 step 2) print(i)
println()
// 02468
for (i in 0..<8 step 2) print(i)
println()
// 0246
for (i in 8 downTo 0 step 2) print(i)
// 86420
//sampleEnd
}
진행(Progressions)
정수 타입(Int, Long, Char)의 범위는 산술 진행으로 취급할 수 있어요. Kotlin에서는 이런 진행을 IntProgression, LongProgression, CharProgression이라는 특별한 타입으로 정의하죠. 진행에는 세 가지 필수 속성이 있어요: 첫 번째 요소인 first, 마지막 요소인 last, 그리고 0이 아닌 step. 첫 번째 요소가 first이고, 이후 요소는 이전 요소에 step을 더한 값이에요. 양의 step을 가진 진행의 반복은 Java/JavaScript의 인덱스 기반 for 루프와 같습니다:
for (int i = first; i <= last; i += step) {
// ...
}
범위를 반복하면서 진행을 암시적으로 만들면, 그 진행의 first와 last는 범위의 양끝이 되고 step은 1이 돼요:
fun main() {
//sampleStart
for (i in 1..10) print(i)
// 12345678910
//sampleEnd
}
사용자 정의 진행 step을 정하려면 범위에 step 함수를 사용하면 돼요:
fun main() {
//sampleStart
for (i in 1..8 step 2) print(i)
// 1357
//sampleEnd
}
진행의 last 요소는 이렇게 계산돼요:
- 양의 step: 끝 값보다 크지 않으면서
(last - first) % step == 0을 만족하는 최댓값. - 음의 step: 끝 값보다 작지 않으면서
(last - first) % step == 0을 만족하는 최솟값.
그래서 last 요소가 지정한 끝 값과 항상 같은 건 아닙니다:
fun main() {
//sampleStart
for (i in 1..9 step 3) print(i) // the last element is 7
// 147
//sampleEnd
}
진행은 각각 Int, Long, Char에 대응하는 Iterable<N>을 구현해요. 그래서 map, filter 같은 다양한 컬렉션 함수에도 그대로 쓸 수 있습니다:
fun main() {
//sampleStart
println((1..10).filter { it % 2 == 0 })
// [2, 4, 6, 8, 10]
//sampleEnd
}
더 알아보기
- 수열(Sequences) — 지연 평가 컬렉션 다루기
- 표준 입력 읽기(Read standard input)