필수적인 함수: filter 와 map
filter함수는 컬렉션을 이터레이션하면서 주어진 람다에 각 원소를 넘겨서 람다가 true를 반환하는 원소만 모은다.
data class Person(val name: String, val age: Int)
fun main() {
val list = listOf(1, 2, 3, 4)
println(list.filter { it%2 == 0 })
val people = listOf(Person("Alice", 29), Person("Bob", 31))
println(people.filter { it.age > 30 })
}
filter 함수는 컬렉션에서 원치 않은 원소를 제거한다. 하지만 filter는 원소를 변환할 수는 없다. 원소를 변환하려면 map 함수를 사용해야 한다.
map 함수는 주어진 람다를 컬렉션의 각 원소에 적용한 결과를 모아서 새 컬렉션을 만든다.
>>> println(list.map { it * it})
>>> println(people.map(Person::name))
// 연쇄시킬 수도 있다.
>>> println(people.filter { it.age > 30 }.map(Person::name))
[1, 4, 9, 16]
[Alice, Bob]
[Bob]
all, any, count, find: 컬렉션에 술어 적용
컬렉션의 모든 원소가 어떤 조건을 만족하는지 판단하는 연산이 있다. 바로 all과 any이다. count함수는 조건을 만족하는 원소의 개수를 반환하며 find 함수는 조건을 만족하는 첫 번째 원소를 반환한다.
어떤 사람의 나이가 29살 이하인지 판단하는 술어 함수를 만들어보자!
val canBeInClub29 = {p : Person -> p.age <= 29}
모든 원소가 술어를 만족하는 궁금하다면 all 함수를 쓴다.
>>> val canBeInClub29 = {p : Person -> p.age <= 29}
>>> val peopleList = listOf(Person("corn", 31), Person("youngCorn", 27))
>>> println(peopleList.all(canBeInClub29))
false
술어를 만족하는 원소가 하나라도 있는지 궁금하면 any를 쓴다.
>>> println(peopleList.any(canBeInClub29))
true
원소의 개수 구하기 count
>>> println(peopleList.count(canBeInClub29))
1
술어를 만족하는 원소 하나 찾기 find
>>> println(peopleList.find(canBeInClub29))
Person(name=youngCorn, age=27)
// 만족하는 원소가 없는 경우 null을 반환한다.
// firstOrNull과 같음
groupBy: 리스트를 여러 그룹으로 이뤄진 맵으로 변경
컬렉션의 모든 원소를 어떤 특성상에 따라 여러 그룹으로 나눌때 사용한다.
사람을 나이에 따라 분류해보자.
>>> val peopleGroupList = listOf(Person("corn", 31), Person("sunghyun", 31), Person("youngCorn", 27))
>>> println(peopleGroupList.groupBy { it.age })
{31=[Person(name=corn, age=31), Person(name=sunghyun, age=31)], 27=[Person(name=youngCorn, age=27)]}
각 그룹은 리스트다. 따라서 groupBy의 결과 타입은 Map<Int, List<Person>>이다.
필요하면 이 맵을 mapKeys나 mapValues 등을 사용해 변경할 수 있다.
flatMap과 flatten: 중첩된 컬렉션 안의 원소 처리
도서관에 있는 책의 저자를 모두 모은 집합을 가져와보자.
data class Book(val title: String, val authors: List<String>)
// 컬렉션에 있는 책을 쓴 모든 저자의 집합
books.flatMap { it.authors }.toSet()
flatMap 함수는 먼저 인자로 주어진 람다를 컬렉션의 모든 객체에 적용(매핑하기/map)하고 람다를 적용한 결과를 얻어지는 여러 리스트를 한 리스트로 한데 모은다.(펼치기/flatten)
>>> val strings = listOf("abc", "def")
>>> println(strings.flatMap { it.toList() })
[a, b, c, d, e, f]
>>> val books = listOf(Book("Thursday next", listOf("Jasper Fforde")),
Book("Mort", listOf("Terry Pratchett")),
Book("Good Omens", listOf("Terry Pratchett", "Neil Gaiman")))
>>> println(books.flatMap{ it.authors }.toSet())
[Jasper Fforde, Terry Pratchett, Neil Gaiman]
book.authors 프로퍼티는 작가를 모아둔 컬렉션이다. flatMap 함수는 모든 책의 작가를 평평한 리스트 하나로 모은다. toSet은 flatMap의 결과 리스트에서 중복을 없애고 집합으로 만든다.
⇒ 리스트의 리스트가 있는데 모든 중첩된 리스트의 원소를 한 리스트로 모아야 한다면 flatMap을 떠올려야 한다.
'프로그래밍 노트 > Kotlin' 카테고리의 다른 글
[Kotlin] 수신 객체 지정 람다: with와 apply (0) | 2020.12.14 |
---|---|
[Kotlin] 코틀린 지연 계산(lazy) 컬렉션 연산 (0) | 2020.12.13 |
[Kotlin] 코틀린 람다 맛보기 (0) | 2020.12.06 |
[Kotlin] 코틀린 object/companion 클래스 (동반객체) (0) | 2020.11.30 |
[Kotlin] 코틀린 데이터 클래스와 클래스 위임 (0) | 2020.11.30 |