본문 바로가기

Kotlin

[Kotlin] 4.람다 In Collection

# 람다 활용법 In Collection

  • Collection 사용 시 람다를 유용하게 쓸 수 있는 경우가 많다

Collection - filter 함수

단어그대로 리스트 원소 중 원하는 원소만 filtering 하겠다는 뜻

리스트의 각 원소를 람다에 넘겨서 람다의 return 값이 true인 원소로 이루어진 리스트를 새로 반환한다

고로, 람다의 마지막 줄은 TRUE/FALSE를 리턴해야 한다

    //filter 예제 (1)
    val listInt = listOf(1, 2, 3, 4)
    listInt.filter { it % 2 == 0 } // [2,4]

    //filter 예제 (2)
    val listStudents = listOf(Student("Tina", 4), Student("Scott", 1))
    listStudents.filter { it.grade >= 4 } //[Student(name=Tina, grade=4)]

 

Collection - map 함수

리스트 원소의 값을 수정해서 새로 만들어서 반환 한다

람다의 마지막 줄은 새로 만들어질 값을 리턴해야 한다

    //map 예제 (1)
    val listInt = listOf(1, 2, 3, 4)
    println(listInt.map { it + 1 }) // [2, 3, 4, 5]
    println(listInt.map {
        it * 100
        it + 1
    }) // [2, 3, 4, 5]   - 'it*100'은 새로 만들어지는 list 와 무관함을 볼 수 있다
    println(listInt.map { it % 2 == 0 }) // [false, true, false, true]

    //map 예제 (2)
    val listStudents = listOf(Student("Tina", 4), Student("Scott", 1))
    println(listStudents.map { it.name }) //[Tina, Scott]  -  'name'으로만 이루어진 새 list를 얻을 수 있다
    println(listStudents.map { it.grade }) //[4, 1] - 'grade'로만 이루어진 새 list를 얻을 수 있다

 

ex) grade가 가장 높은 학생 이름 구하기

val listStudents = listOf(Student("Tina", 4), Student("Scott", 1))
istStudents.filter { it.grade == listStudents.maxByOrNull(Student::grade)!!.grade} //[Tina]

위 식은 Collectin 사용 시 람다안에 람다를 쓴 경우인데, 동작을 알아보기 위해 아래와 같이 print를  추가해 보자

println(listStudents.filter {
    println("filter")
    it.grade == listStudents.maxByOrNull { it ->
        println("maxByOrNull")
        it.grade
    }!!.grade
})

[결과]
//    filter
//    maxByOrNull
//    maxByOrNull
//    filter
//    maxByOrNull
//    maxByOrNull

원소 2개 짜리 리스트로 실행했을 뿐인데도, 수행 복잡도가 올라가는 것을 볼 수 있다

그러므로, Collection에서의 람다 중첩은 조심해서 쓰도록 하자

위의 식을 그나마 효율적이게 만들어보면

    val maxGrade = listStudents.maxByOrNull { it -> it.grade }!!.grade
    listStudents.filter { it.grade == maxGrade }

print 해 보면

val maxGrade = listStudents.maxByOrNull { it ->
    println("maxByOrNull")
    it.grade}!!.grade

listStudents.filter {
    println("filter")
    it.grade == maxGrade
}

[결과]
//    maxByOrNull
//    maxByOrNull
//    filter
//    filter

수행 횟수가 줄어드는 것 을 볼 수 있다

 

*map의 경우에서 key와, value에 대해 각각의 filter/map 함수가 있다 

 filterKeys, mapKeys, filterValues, mapValues

 

 

Collection - 원소 조건 판별

all / any / count / find

all : 모든 원소가 조건을 만족하는지  TRUE/FALSE 반환

any : 적어도 1개의 원소가 조건을 만족하는지 TRUE/FALSE 반환

count : 조건을 만족하는 원소 갯수 반환 

find : 조건을 만족하는 가장 첫번째 원소를 반환 

data class Student constructor(val name: String, val grade: Int)

val isGrade4 = { student: Student -> student.grade == 4 }
val isGrade5 = { student: Student -> student.grade == 5 }
val students = listOf(Student("Tina", 4), Student("Scott", 1), Student("July", 4))

    //조건의 만족에 대한 Boolean 갑을 반환
    println(students.all(isGrade4)) //false
    println(students.any(isGrade4)) //true
    println(students.count(isGrade4)) //2

    //조건을 만족하는 가장 첫번째 원소를 반환한다. 없을 경우 null.
    println(students.find(isGrade4)) // Student(name=Tina, grade=4)
    println(students.find(isGrade5)) // null

 

 

Collection - 분류

groupBy : 특성/조건이 동일한 원소들을 group지어 반환한다

리턴 형태 =

Map<K, List<T>> 

Map<동일 특성, 원소 List>

    println(students.groupBy { it.grade })
    //{4=[Student(name=Tina, grade=4), Student(name=July, grade=4)], 1=[Student(name=Scott, grade=1)]}
    
    println(students.groupBy(isGrade4))
    //{true=[Student(name=Tina, grade=4), Student(name=July, grade=4)], false=[Student(name=Scott, grade=1)]}

 

 

Collection - 리스트의 리스트 원소들을 한데 모아 보고 싶을 때 (list of list)

flatten/flatMap

flatten() : 리스트 안의 원소가 리스트 일 때, 원소 리스트 들을 값을 한 데 모아서 List로 반환한다

flatMap{} : flatten과 동일 하지만 원소 리스트의 값을 변경해서 반환하고 싶을 경우 사용한다

 

    val strings = listOf("abc".toList(), "cde".toList())
//    [[a, b, c], [c, d, e]]


//  (1)그냥 펼쳐보이기
    println("flatten() = " + strings.flatten())
//  [결과]  flatten() = [a, b, c, c, d, e]

                                                        1) [a, b, c].map{ ~ }    =>  [A,B,C]
//  (2)대문자 변경 후 펼쳐보이기                          2) [c, d, e].map{ ~ }    =>  [C,D,E]
    println("flatMap() = " + strings.flatMap { charList -> charList.map { char -> char.uppercase() } })
//  [결과]  flatMap() = [A, B, C, C, D, E]

 


출처 : Kotlin In Action - 에이콘 출판사

(위 도서를 학습하고 개인 학습용으로 정리한 내용입니다)

'Kotlin' 카테고리의 다른 글

[Kotlin] 4.람다 - 함수형 인터페이스(SAM 인터페이스)  (0) 2021.12.04
[Kotlin] 4.람다 In Collection(Sequence)  (0) 2021.11.17
[Kotlin] 4.람다 - 기본  (0) 2021.11.15
[Kotlin] 3. Object  (0) 2021.11.15
[Kotlin] 3. Data Class, by  (0) 2021.11.07