컬렉션과 람다식
코틀린에서 정말 편했던 기능 중 하나인 컬렉션 + 람다식입니다.
자바와 마찬가지로, 코틀린은 배열, 리스트, 집합, Map 등에
sum, avg, sort, max, min, reverse, contain 등 여러 메소드를 지원합니다.
(자료구조와 타입 따라 지원되는 메소드는 조금씩 다릅니다.)
그 중, 코틀린에서는 위 메소드들에 람다식을 사용한 여러 편의기능을 제공하는데요.
대표적인 몇 가지의 기능들을 알아보겠습니다.
아래 메소드들은 대부분 List, Set, Map등 컬렉션 뿐만 아닌 배열에서도 사용이 가능합니다.
forEach, forEachIndex
val arr = arrayOf(10, 20, 123, 64, 12)
arr.forEach { println(it) }
// 출력
10
20
123
64
12
이미 여러번 나왔던 forEach는 자료구조 내 원소를 하나씩 순회하는 반복문입니다.
val arr = arrayOf(10, 20, 123, 64, 12)
arr.forEachIndexed { index, i ->
println("index: $index, value: $i")
}
// 출력
index: 0, value: 10
index: 1, value: 20
index: 2, value: 123
index: 3, value: 64
index: 4, value: 12
forEachIndexd로 자료구조의 인덱스와 값을 함께 순회할 수 있습니다.
all, any
class Person(val name: String, val age: Int, val height: Int)
fun main() {
val persons = listOf(
Person("홍길동", 29, 160),
Person("전우치", 31, 180),
Person("사스케", 31, 170)
)
println("모두 키가 170 이상인가? ${persons.all { it.height >= 170 }}")
println("모두 나이가 20 이상인가? ${persons.all { it.age >= 20 }}")
println("한 명이라도 키가 170 이상인가? ${persons.any { it.height >= 170 }}")
println("한 명이라도 나이가 40 이상인가? ${persons.any { it.age >= 40 }}")
}
// 출력
모두 키가 170 이상인가? false
모두 나이가 20 이상인가? true
한 명이라도 키가 170 이상인가? true
한 명이라도 나이가 40 이상인가? false
all은 데이터가 모두 조건을 만족하는지 검사하는 메소드입니다.
모든 데이터가 조건을 만족해야만 true를 반환하며,
하나라도 틀리면 false를 반환합니다.
any는 조건에 만족하는 데이터가 있는지 검사하는 메소드입니다.
하나라도 조건을 만족하는 데이터가 있을 경우 true를 반환합니다.
모든 데이터가 조건을 만족하지 않을 때 false를 반환합니다.
위와 같이, 컬렉션 람다식은 객체를 다룰 때 정말 편합니다.
filter
class Person(val name: String, val age: Int, val height: Int)
fun main() {
val persons = listOf(
Person("홍길동", 29, 160),
Person("전우치", 31, 180),
Person("사스케", 31, 170)
)
val person31 = persons.filter { it.age == 31 }
person31.forEach { println("${it.name} ${it.age}") }
}
// 출력
전우치 31
사스케 31
==================================================================
val arr = arrayOf(3, 4, 5, 6, 8, 2, 12, 443, 6576, 75)
arr.filter { it % 2 == 0 }.forEach { println(it) } // 짝수만 뽑아오기
// 출력
4
6
8
2
12
6576
filter는 조건에 맞는 원소들만 뽑아올 때 사용하는 메소드입니다.
람다식 안의 조건문이 참이 되는 원소들만 가져와 필터링하며,
위 코드는 나이(age)가 31살인 사람만 뽑는데 사용하였습니다.
아래 코드는 배열 내 원소중 짝수(2로 나눴을 때 나머지가 0)만 필터링한 예제입니다.
count
class Person(val name: String, val age: Int, val height: Int)
fun main() {
val persons = listOf(
Person("홍길동", 29, 160),
Person("전우치", 31, 180),
Person("사스케", 31, 170)
)
val person31 = persons.count { it.age == 31 }
println(person31)
}
// 출력
2
count { } 는 특정 조건에 맞는 원소의 개수를 반환합니다.
위 코드에서는 나이가 31살인 사람만 카운트하였습니다.
map
val arr = arrayOf(10, 20, 30, 40, 50)
val new = arr.map { it * 2 }
new.forEach { println(it) }
// 출력
20
30
60
80
100
map은 forEach와 비슷하게 자료구조 내 원소들을 순회합니다.
다만, map은 반환값이 존재하며,
저는 주로 자료구조 내 값을 가공할 때 쓰곤 합니다.
코딩테스트를 할 때 특히나 많이 쓰는 녀석인데,
10 12 13 등으로 입력을 받고, 이걸 숫자형으로 반환받고 싶을 땐,
val arr = readln().split(” “).map{ it.toInt } 로 쓰면 간단히 숫자형 리스트를 받을 수 있습니다.
first, last
val arr = arrayOf(10, 12, 33, 14, 15, 20)
val firstOdd = arr.first { it % 2 == 1 }
println(firstOdd)
val lastOdd = arr.last { it % 2 == 1 }
println(lastOdd)
// 출력
33
15
first / last는 조건에 맞는 첫 번째 / 마지막 원소를 반환하는 메소드입니다.
위 코드에선 각각 첫 번째 홀수, 마지막 홀수를 구하는 용도로 사용하였습니다.
indexOfFirst, indexOfLast
val arr = arrayOf(10, 12, 33, 14, 15, 20)
val firstOdd = arr.indexOfFirst { it % 2 == 1 }
println(firstOdd)
val lastOdd = arr.indexOfLast { it % 2 == 1 }
println(lastOdd)
// 출력
2
4
indexOfFirst / indexOfLast는 first/last와 비슷하게,
조건에 맞는 첫 번째 / 마지막 원소의 인덱스를 반환하는 메소드입니다.
위 코드에선 각각 첫 번째 홀수, 마지막 홀수의 인덱스를 구하는 용도로 사용하였습니다.
sumOf
val arr = arrayOf(10, 20, 30, 40, 50)
val sum = arr.sumOf { it * 2 }
println(sum)
// 출력
300
===============================================================================
class Person(val name: String, val age: Int, val height: Int)
fun main() {
val persons = listOf(
Person("홍길동", 29, 160),
Person("전우치", 31, 180),
Person("사스케", 31, 170)
)
val ageSum = persons.sumOf { it.age }
println(ageSum)
}
// 출력
91
sumOf는 람다식을 사용해 값들의 합을 구할 때 쓰입니다.
위 코드는 각 원소에 * 2씩을 하여 총 합을,
아래 코드는 각 객체의 나이의 합을 구한 코드입니다.
sortedBy, sortedByDescending
class Person(val name: String, val age: Int, val height: Int)
fun main() {
val persons = listOf(
Person("홍길동", 29, 160),
Person("전우치", 31, 180),
Person("흥부", 32, 175),
Person("놀부", 33, 175),
Person("사스케", 34, 170),
Person("나루토", 35, 175),
)
persons.sortedBy { it.age }.forEach { println("${it.name} ${it.age} ${it.height}") }
}
// 출력
홍길동 29 160
전우치 31 180
흥부 32 175
놀부 33 175
사스케 34 170
나루토 35 175
=======================================================================
fun main() {
val nums = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)
nums.sortedByDescending { it % 3 }.forEach { println(it) }
}
// 출력
2
5
8
11
14
17
1
4
7
10
13
16
3
6
9
12
15
18
sortedBy는 일반적인 sort 메소드에 람다식을 사용할 수 있게 해줍니다.
위 코드는 나이(age)를 기준으로 정렬을 한 코드입니다.
아래 코드는 각 원소를 3으로 나눈 것을 기준으로 내림차순 정렬한 코드입니다.
sortedBy는 기본적으로 오름차순이며,
내림차순으로 하고 싶을 sortedByDescending을 사용하면 됩니다.
이 외에도 코틀린의 컬렉션은 다양한 기능을 지원합니다.
자세한 내용은 코틀린 공식 문서를 참고해주세요.
https://kotlinlang.org/docs/home.html
Kotlin Docs | Kotlin
kotlinlang.org
'코틀린 파헤치기 > 3부. 코틀린 고급' 카테고리의 다른 글
[코파기 3부] 10. 코틀린과 꼬리재귀와 tailrec (0) | 2023.07.25 |
---|---|
[코파기 3부] 8. 코틀린과 컬렉션 프레임워크 (2) : Map (0) | 2023.03.27 |
[코파기 3부] 7. 코틀린과 컬렉션 프레임워크 (1) : Set (0) | 2023.03.27 |
[코파기 3부] 6. 코틀린과 함수형 프로그래밍 (2) : 람다식 (0) | 2023.03.24 |
[코파기 3부] 5. 코틀린과 함수형 프로그래밍 (1) : 함수형 프로그래밍이란? (0) | 2023.03.24 |