ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 18강. 코틀린에서 컬렉션을 함수형으로 다루는 방법
    BackEnd/Kotlin 2024. 4. 14. 08:00
    반응형
    1. filter와 map
    2. 다양한 컬렉션 처리 기능
    3. groupBy / associateBy
    4. flatten / flatMap

     

    filter와 map

    fun main() {
        val fruits = listOf(
            Fruit("사과", 1_000),
            Fruit("사과", 1_200),
            Fruit("사과", 1_200),
            Fruit("사과", 1_500),
            Fruit("바나나", 3_000),
            Fruit("바나나", 3_200),
            Fruit("바나나", 2_500),
            Fruit("수박", 10_000),
        )
    
        val apples = fruits.filter { fruit -> fruit.name == "사과" }
    
        // filter 에서 인덱스가 필요하다면 filterIndexed 사용합니다.
        val apples2 = fruits.filterIndexed { idx, fruit ->
            println(idx)
            fruit.name == "사과"
        }
    
        // 사과의 가격들을 알기위해 filter 이후 map을 수행합니다.
        val applePrices = fruits.filter { fruit -> fruit.name == "사과" }
            .map { fruit -> fruit.price }
    
        // map에서 인덱스가 필요하다면 mapIndexed 를 사용합니다.
        val applePrices2 = fruits.filter { fruit -> fruit.name == "사과" }
            .mapIndexed { idx, fruit ->
                println(idx)
                fruit.price
            }
    }

     

      Mapping의 결과가 null이 아닌 것만 가져오고 싶은 경우, mapNotNull을 사용하면 됩니다.

        val values = fruits.filter { fruit -> fruit.name == "사과" }
            .mapNotNull { fruit -> fruit.nullOrVale() }

     

    다양한 컬렉션 처리 기능

    all: 조건을 모두 만족하면 true, 그렇지 않으면 false 입니다.

      val isAllApple = fruits.all { fruit -> fruit.name == "사과" }

    none: 조건을 모두 불만족하면 true, 그렇지 않으면 false 입니다.

      val isNoApple = fruits.none { fruit -> fruit.name == "사과" }

    any: 조건을 하나라도 만족하면 true, 그렇지 않으면 false 입니다.

      val isBigPrice = fruits.any { fruit -> fruit.price >= 10_000 }

    count: 개수를 셉니다.

      val fruitCount = fruits.count()

    sortedBy: (오름차순) 정렬을 합니다.

      val sortedByFruit = fruits.sortedBy { fruit -> fruit.price }

    sortedByDescending: (내림차순) 정렬을 합니다.

      val sortedByDescFruit = fruits.sortedByDescending { fruit -> fruit.price }

    distinctby: 변형된 값을 기준으로 중복을 제거합니다.

      val distinctFruitNames = fruits.distinctBy { fruit -> fruit.name }
        .map { fruit -> fruit.name }

    first: 첫번째 값을 가지고 옵니다. 값이 없을 경우 예외가 발생합니다.

    firstOrNull: 첫번째 값 또는 null을 가지고 옵니다.

    last: 마지막 값을 가지고 옵니다. 값이 없을 경우 예외가 발생합니다.

    lastOrNull: 마지막 값 또는 null을 가지고 옵니다.

     

    groupBy / associateBy

      groupBy는 특정 key로 key에 해당하는 객체들을 매핑할 때 사용합니다. 다음은 과일이름을 key로, key에 해당하는 과일들을 value로 하는 Map을 생성하는 코드입니다.

        val map: Map<String, List<Fruit>> = fruits.groupBy { fruit -> fruit.name }

      key와 value를 동시에 처리할 수도 있습니다. 다음은 과일이름을 key로, key에 해당하는 가격들을 value로 하는 Map을 생성하는 코드입니다.

        val map2: Map<String, List<Int>> =
            fruits.groupBy({ fruit -> fruit.name }, { fruit -> fruit.price })

     

      중복되지 않은 key를 가지고 Map을 생성할 때는 associateBy를 사용할 수 있습니다.

        // Fruit 객체 내 중복되지 않는 id 필드가 필요합니다.
        val map: Map<Long, Fruit> = fruits.associateBy { fruit -> fruit.id }
        val map2: Map<Long, Long> = fruits
          .associateBy({ fruit -> fruit.id }, { fruit -> fruit.price })

     

      Map에 대해서도 앞선 기능들을 대부분 사용할 수 있습니다. 다음은 groupBy로 생성한 map에 filter 를 사용한 코드입니다.

        val map: Map<String, List<Fruit>> = fruits.groupBy { fruit -> fruit.name }
          .filter { (key, value) -> key == "사과" }

     

    flatten

      중첩되어 있는 컬렉션을 중첩 해제하기 위해 사용합니다. 즉, 평탄화 합니다. 다음은 List<List<>>를 List<> 형태로 평탄화 합니다.

        // flatten
        val numbers = listOf(listOf(1,2,3), listOf(4, 5), listOf(6))
        val result = numbers.flatten()
        println(result) // [1, 2, 3, 4, 5, 6]

     

    flatMap

      인자로 주어진 람다를 컬렉션에 적용하고 flatten 합니다.

        val numbers = listOf(listOf(1, 2, 3), listOf(4, 5), listOf(6))
        val result2 = numbers.flatMap { it.map { "number $it" } }
        println(result2) // [number 1, number 2, number 3, number 4, number 5, number 6]

     

      평탄화 작업만 필요한 경우 flatten을 사용하고, 별도 처리가 필요한 경우 flatMap을 사용하면 됩니다.

     

     

     

    감사합니다.

    반응형

    댓글

Designed by Tistory.