PS 문제를 하나씩 풀다 보니, 공부가 필요하다고 느낀 문법을 정리한 글입니다.
알고리즘 문제를 풀다 보면 두 개 또는 세 개의 값을 하나로 묶어서 다뤄야 하는 경우가 있습니다.
예를 들어 좌표처럼(x, y)를 함께 저장하거나, 상태값을 세 개씩 묶어서 처리해야 할 때가 있습니다.
이럴 때 사용할 수 있는 것이Pair와Triple입니다.
이번 글에서는 Kotlin에서 여러 값을 묶어 사용하는 방법인 Pair와 Triple에 대해 정리해보려고 합니다.
Pair는 이름 그대로 두 개의 값을 하나의 쌍으로 묶는 클래스입니다.
서로 다른 타입의 값도 함께 저장할 수 있기 때문에, 간단한 데이터를 임시로 묶어둘 때 자주 사용됩니다.
예를 들어 아래처럼 사용할 수 있습니다.
fun main() {
val (a, b) = Pair(1, "x")
println(a) // 1
println(b) // x
}
위 코드에서는 Pair(1, "x")를 만들고,
구조 분해 선언을 통해 각각 a, b로 꺼내 사용하고 있습니다.
즉, Pair는 다음과 같이 이해하시면 됩니다.
firstsecond직접 접근하면 아래처럼 사용할 수도 있습니다.
fun main() {
val pair = Pair(1, "x")
println(pair.first) // 1
println(pair.second) // x
}
또는 Kotlin에서는 to를 사용해서 조금 더 자연스럽게 만들 수도 있습니다.
fun main() {
val pair = 1 to "x"
println(pair.first) // 1
println(pair.second) // x
}
Pair를 조금 더 응용해서 보면,
백준 11399번 문제에서도 이런 식으로 활용할 수 있습니다.
이 문제는 사람마다 돈을 인출하는 데 걸리는 시간이 주어졌을 때,
전체 사람이 기다리는 시간의 합이 최소가 되도록 정렬한 뒤 그 합을 구하는 문제입니다.
사람 번호와 걸리는 시간을 하나의 쌍으로 묶으면,
정렬 기준과 데이터를 함께 관리하기가 편해집니다.
import java.io.StreamTokenizer
fun main() = with(StreamTokenizer(System.`in`.bufferedReader())) {
fun nextInt(): Int {
nextToken()
return nval.toInt()
}
val n = nextInt()
val atm = Array(n) { i -> Pair(i + 1, nextInt()) }
atm.sortBy { it.second }
var prefix = 0
var result = 0
for ((_, time) in atm) {
prefix += time
result += prefix
}
print(result)
}
Pair로 묶어서 배열에 저장합니다.second를 기준으로 오름차순 정렬합니다.여기서 중요한 점은 다음과 같습니다.
first : 첫 번째 값second : 두 번째 값sortBy { it.second } : 두 번째 값을 기준으로 정렬또한 반복문에서 아래처럼 구조 분해를 사용하면 더 읽기 쉬워집니다.
for ((_, time) in atm) {
...
}
사람 번호는 실제 계산에 사용하지 않기 때문에 _로 받고,
필요한 시간값만 time으로 꺼내 사용한 것입니다.
다만 이 문제는 사실 시간값만 정렬해도 풀 수 있기 때문에,
Pair는 “두 값을 함께 다루는 연습” 용도로 보시면 이해하기 좋습니다.
Triple은 Pair와 비슷하지만,
세 개의 값을 하나로 묶을 수 있는 클래스입니다.
예를 들어 아래처럼 사용할 수 있습니다.
fun main() {
val (a, b, c) = Triple(2, "x", listOf(null))
println(a) // 2
println(b) // x
println(c) // [null]
}
Triple의 각 값은 다음과 같이 접근할 수 있습니다.
firstsecondthirdfun main() {
val triple = Triple(2, "x", listOf(null))
println(triple.first) // 2
println(triple.second) // x
println(triple.third) // [null]
}
Pair와 마찬가지로, 서로 다른 타입의 값도 함께 저장할 수 있습니다.
Pair와 Triple은 데이터 클래스처럼 copy()도 사용할 수 있습니다.
즉, 기존 값을 바탕으로 일부만 바꾼 새 객체를 만들 수 있습니다.
fun main() {
val a = Triple(2, "x", listOf(null))
val b = a.copy(
first = 1,
second = "a",
third = listOf(null)
)
println(b.first) // 1
println(b.second) // a
println(b.third) // [null]
}
위 코드에서는 기존 Triple을 복사하면서
첫 번째 값과 두 번째 값만 바꾸어 새로운 객체를 만들고 있습니다.
Pair와 Triple은 간단하고 편리하지만,
항상 가장 좋은 선택은 아닐 수도 있습니다.
예를 들어 아래처럼 쓰면 처음에는 편할 수 있습니다.
val student = Pair("Smith", 20)
하지만 시간이 지나면 first, second가 각각 무엇을 의미하는지 헷갈릴 수 있습니다.
그래서 의미가 분명한 데이터라면 data class를 사용하는 편이 더 읽기 좋습니다.
data class Student(
val name: String,
val age: Int
)
즉,
Pair, Tripledata class이렇게 구분해서 사용하는 편이 좋습니다.
이번 글에서는 Kotlin의 Pair와 Triple에 대해 정리해보았습니다.
Pair와 Triple은 여러 값을 간단하게 묶어서 사용할 수 있게 해주는 도구입니다.
특히 알고리즘 문제를 풀 때 좌표, 상태, 인덱스와 값처럼 관련된 데이터를 함께 저장하고 싶을 때 유용합니다.
정리하면 다음과 같습니다.
Pair는 두 개의 값을 묶습니다.Triple은 세 개의 값을 묶습니다.first, second, third로 접근할 수 있습니다.data class가 더 적합할 수 있습니다.즉, Pair와 Triple은 문제 풀이에서 빠르게 값을 묶어야 할 때 유용한 도구이고,
코드의 의미를 더 분명히 드러내야 하는 상황이라면 data class까지 함께 고려하는 것이 좋습니다.