[Kotlin] 4. 대상을 이터레이션: while 과 for

2023. 3. 23. 23:50Programming Languages/Kotlin

1. while 문

whlie 문과 do while 문은 Java와 같다.

while (조건) {
    /* ... */
}

do {
    /* ... */
} while (조건)

2. 수에 대한 이터레이션: 범위와 수열

for 문은 Java의 for-each 문만 존재한다. 즉 for (int i = 0; i < n; i++)과 같이 사용할 수 없다. 대신 범위(range)를 사용한다.

범위는 기본적으로 두 값으로 이루어진 구간이다. 그 값은 보통 정수 등의 숫자 타입의 값이며 .. 연산자로 시작 값과 끝 값을 연결해서 범위를 만든단.

val oneToTen = 1..10

코틀린의 범위는 기본적으로 닫힌 구간 또는 양 끝을 포함하는 구간이다. 즉 마지막 값이 항상 범위에 포함되어 있다.

일정한 값을 증가시키면서 이터레이션할 수도 있는데 이 경우를 수열(progression)이라고 부른다.

fun fizzbuzz(i: Int) = when {
    i % 15 == 0 -> "Fizzbuzz"
    i %  3 == 0 -> "Fizz"
    i %  5 == 0 -> "Buzz"
    else -> "${i}"
}

// 1부터 100까지(100 포함) 순서대로 반복
for (i in 1.100) {
    println(fizzbuzz(i))
}

// 100부터 1까지(1포함) 2씩 감소하면서 반복
for (i in 100 downTo 1 step 2) {
    println(fizzbuzz(i))
}

// 끝 범위를 포함하고 싶지 않으면 until 함수를 사용
for (i in 1 until 100 step 3) {
    println(fizzbuzz(i))
}

3. Map에 대한 이터레이션

val binaryReps = TreeMap<Char, String>()

// 문자에도 .. 연산자 적용 가능
for (c in 'A'..'Z') {
    val binary = Integer.toBinaryString(c.toInt())
    binaryReps[c] = binary // map.put(c, binary)
}

// 맵의 키와 값을 구조 분해 문법으로 사용
for ((letter, binary) in binaryReps) {
    println("${letter} = ${binary}")
}

4. in으로 컬렉션이나 범위의 원소 검사

// ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'

// !(0 <= n && n <= 9)
fun isNotDigit(n: Int) = n !in 0..9

fun recognize(c: Char) = when (c) {
    in '0'..'9' -> "It's a digit"
    in 'a'..'z' && 'A'..'Z' -> "It's a letter!"
    else -> "I don't know"
}

범위는 단순히 문자에 국한되지 않는다. 비교 가능한 클래스(java.lang.Comparable 인터페이스를 구현한 클래스)라면 그 클래스의 인스턴스 객체를 사용해 범위를 만들 수 있다. Comparable을 사용하는 범위의 경우 그 범위 내의 모든 객체를 이터레이션할 수는 없지만 값이 범위 안에 속하는지를 결정한다.

// "Java" <= "Kotlin" && "Kotlin" <= "Scala"
// String의 Comparable 구현이 알파벳 순서로 비교한다.
println("Kotlin" in "Java".."Scala") // true

println("Kotlin" in setOf("Java", "Scala")) // false