Develop!/Kotlin

람다 in Kotlin

체리필터 2023. 9. 25. 09:38
728x90
반응형

람다식을 Kotlin에서도 사용할 수 있다.

가장 많이 사용하는 람다로 map이 있다. mapping의 약자인 듯 보인다. 기존 값을 사용하여 새로운 값을 맵핑해 준다는 의미로 보이는데 아래와 같이 사용한다.

fun map() {
    val list = listOf(1, 2, 3, 4)
    val result = list.map { n:Int -> "[$n]" }
    val result2 = list.map { n -> "[$n]" }
    val result3 = list.map { "[${it}]" }

    println(result)
    println(result2)
    println(result3)

    val listChar = listOf('a', 'b', 'c', 'd')
    val resultChar = listChar.map { "[${it.toUpperCase()}]" }
    println(resultChar)
}

위의 3가지 경우(result ~ result3) 모두 같은 값을 출력한다.

동일한 list를 동일한 형식으로 바꾸는 다른 방법임을 알 수 있다. 람다 식 안에서 받아지는 변수명은 자동으로 it 이 된다.

문자에서도 비슷한 방식으로 사용할 수 있음을 4번째 예에서 볼 수 있다.

람다 중에 List를 하나의 문자로 합쳐주는 joinToString 도 있다. 사용법은 아래와 같다.

fun joinToString() {
    val list = listOf(1, 2, 3, 4)

    val resultJoinToString = list.joinToString(" ") { "[$it]" }
    val resultJoinToString2 = list.joinToString(separator = " ", transform = { "[$it]"})
    println(resultJoinToString)
    println(resultJoinToString2)
}

1 ~ 4까지의 숫자를 문자형태로 바꾸어서 합쳐주는 것인데, joinToString이 여러개의 파라미터를 받고 있으므로 () 뒤에 람다를 써서 사용할 수 있다.

같은 효과지만 명시적으로 transform 이라는 파라미터 이름에 람다를 정의할 수도 있다.

map과 비슷하지만 mapIndexed라는 람다도 사용해 볼 수 있다.

mapIndexed는 index(순서)를 같이 반환해 준다.

fun mapIndexed() {
    val list = listOf('a', 'b', 'c')
    val result = list.mapIndexed { index, element -> "[$index: $element]" }
    val result2 = list.mapIndexed { index, _ -> "[$index]" }
    val result3 = list.mapIndexed { _, element -> "[$element]" }

    println(result)
    println(result2)
    println(result3)
}

mapIndexed는 index와 원소를 인자로 받는다. 두 가지 중 한 개의 값을 받지 않고 싶을 때는 "_"를 사용하면 된다.

람다를 사용하는 이유 중 하나는 가독성이 높은 코드를 만들 수 있기 때문이다. 다음의 예를 통해 알 수 있다.

2보다 큰 숫자만 골라내는 전통적인 방법이다.

fun iterateFilter() {
    val list = listOf(1, 2, 3, 4)
    val result =  mutableListOf<Int>()
    for (i in list) {
        if (i > 2) {
            result += i
        }
    }
    println(result)
}

간단한 코드이기 때문에 금방 알 수있지만 이러한 for 문들이 코드 곳곳에 녹아 있다면 코드를 읽어 내려가기가 쉽지 않다. 람다를 쓸 경우에는 아래와 같이 간단하게 사용 가능하다.

fun filter() {
    val list = listOf(1, 2, 3, 4)
    val even = list.filter { it % 2 == 0 }
    val greaterThan2 = list.filter { it > 2 }

    println(even)
    println(greaterThan2)
}

단순이 filter라는 람다에 조건을 서술한 술어(boolean을 반환하는 predicate)을 작성하면 된다. filter 함수의 결과는 아래와 같다.

람다가 잘 동작함을 볼 수 있다.

람다는 변수에 담아 재사용할 수 있다.

fun filter() {
    val list = listOf(1, 2, 3, 4)

    val isEven = { e:Int -> e % 2 == 0}
    val result = list.filter(isEven)
    val result2 = list.any(isEven)
    println(result)
    println(result2)
}

위의 코드에서는 isEven 이라는 람다를 정의해 두고 두 곳에서 재활용 했다. 결과는 아래와 같다.

람다 밖의 요소를 참조할 수 있는 것을 클로져라 한다. 다음과 같은 경우를 참고할 수 있다.

fun foreachClosure() {
    val list = listOf(1, 5, 7, 10)
    var sum = 0
    val divider = 5

    list.filter { it % divider == 0 }
        .forEach { sum += it }

    println(sum)

    val resultSum = list.filter { it % divider == 0 }.sum()
    println(resultSum)
}

divider 또는 sum과 같은 변수를 람다 안에서 사용하게 되는 경우 이를 클로져라 한다.

위와 같이 foreach를 사용하게 될 경우, 컬랙션의 매 원소의 값에 람다를 적용할 수 있다. 단순히 값을 sum 하는 경우라면 foreach를 사용하는 대신에 바로 sum 함수를 사용할 수 있다.

728x90
반응형

'Develop! > Kotlin' 카테고리의 다른 글

멤버참조 in Kotlin  (0) 2023.09.27
컬렉션에 대한 연산 in Kotlin  (0) 2023.09.25
제네릭스 in Kotlin  (0) 2023.09.22
안전한 호출과 엘비스 연산자 in kotlin  (0) 2023.09.14
Null이 될 수 없는 타입 in Kotlin  (0) 2023.09.06