2. [4] 대상을 이터레이션: while과 for 루프

(1) while 루프

  • Kotlin에는 while 루프와 do-while 루프가 존재함.
  • 해당 루프는 매우 단순하며, 코틀린에서 추가한 기능 조차 없음

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

  • Kotlin에서는 범위(Range)를 사용하여 루프를 표현한다.
  • 어떤 범위에 속한 값을 일정한 순서로 이터레이션하는 경우를 수열이라고 부른다.
fun fizzBuzz(i: Int) = when {
  i % 15 == 0 -> "FizzBuzz"
  i % 3 == 0  -> "Fizz"
  i % 5 == 0  -> "Buzz"
  else -> "$i"
}
for(i in 1..100) {
  print(fizzBuzz(i))
}
// 1 2 Fizz 4 Buzz Fizz 7 ...
for(i in 100 downTo 1 step 2) {
  print(fizzBuzz(i))
}
// Buzz 98 Fizz 94 92 FizzBuzz 88 ...
  • 증가 값 step을 갖는 수열에 대해서 이터레이션한 모습이다.
  • 증가 값을 사용하면 수를 건너뛸 수 있으며, 증가 값을 음수로 만들면 역방향 수열을 만들 수 있다.
  • '..' 는 항상 범위의 끝 값을 포함한다. 그 외로, 닫힌 범위에 대해서 이터레이션 하기 위해서는 until 함수를 사용하면 된다.

(3) 맵에 대한 이터레이션

val binaryReps = TreeMap<Char, String>()      // Key에 대해 정렬하기 위해 TreeMap 사용

for(c in 'A'..'F') {
  val binary = Integer.toBinaryString(c.toInt()) // ASCII code -> 2진 표현
  binaryReps[c] = binary // c를 Key로 c의 2진 표현을 맵에 넣는다.
}

for((letter, binary) in binaryReps) {
  println("$letter = $binary")  // Map의 Key와 값을 두 변수에 대입(Map에 대한 이터레이션)
}
  • '..' 연산자는 숫자 타입의 값 뿐만 아니라 문자 타입에 대한 값에도 적용할 수 있다.
  • 해당 코드에서는 get, put을 사용하는 대신, map[key]나 map[key] = value를 사용해 값을 가져오고 설정할 수 있다.
val list = arrayListOf("10", "11", "1001")

for((index, element) in list.withIndex()) { // 인덱스와 함께 컬렉션을 이터레이션
  println("$index : $element")
}

// 0 : 10
// 1 : 11
// 2 : 1001
  • 맵이 아닌 컬렉션에서도 활용할 수 있다.
  • 원소의 현재 인덱스를 유지하면서 컬렉션을 이터레이션하는 것이 가능하다.

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

fun recognize(c: Char) = when(c) {
  in '0'..'9' -> "It's a digit"
  in 'a'..'z' -> "It's a letter"
  else -> "I don't know"
}
  • 비교가 가능한 클래스라면 해당 클래스의 인스턴스 객체를 사용하여 범위를 만들 수 있다.
println("Kotlin" in "Java".."Scala")  // true
println("Kotlin" in setOf("Java", "Scala")) // false