그룹핑

그룹핑 (Grouping)

Kotlin 표준 라이브러리는 컬렉션 요소를 그룹으로 묶기 위한 확장 함수를 제공해요. 기본 함수인 groupBy()는 람다 함수를 받아 Map을 반환합니다. 이 맵에서 각 키는 람다의 결과이고, 그에 대응하는 값은 그 결과를 반환하는 요소들의 List예요. 이 함수는 예를 들어 String 리스트를 첫 글자별로 그룹화하는 데 쓸 수 있어요.

groupBy()를 두 번째 람다 인자(값 변환 함수)와 함께 호출할 수도 있어요. 람다가 두 개 있는 groupBy()의 결과 맵에서는 keySelector 함수가 만든 키가 원래 요소 대신 값 변환 함수의 결과에 매핑됩니다.

이 예시는 groupBy() 함수로 문자열을 첫 글자별로 그룹화하고, 결과 Mapfor 연산자로 순회하며 그룹들을 확인한 다음, valueTransform 함수를 사용해 값을 대문자로 변환하는 과정을 보여줘요.

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four", "five")

    // Groups the strings by their first letter using groupBy()
    val groupedByFirstLetter = numbers.groupBy { it.first().uppercase() }
    println(groupedByFirstLetter)
    // {O=[one], T=[two, three], F=[four, five]}

    // Iterates through each group and prints the key and its associated values
    for ((key, value) in groupedByFirstLetter) {
        println("Key: $key, Values: $value")
    }
    // Key: O, Values: [one]
    // Key: T, Values: [two, three]
    // Key: F, Values: [four, five]

    // Groups the strings by their first letter and transforms the values to uppercase
    val groupedAndTransformed = numbers.groupBy(keySelector = { it.first() }, valueTransform = { it.uppercase() })
    println(groupedAndTransformed)
    // {o=[ONE], t=[TWO, THREE], f=[FOUR, FIVE]}
//sampleEnd
}

요소를 그룹으로 묶은 다음 모든 그룹에 한 번에 연산을 적용하고 싶다면 groupingBy() 함수를 사용해요. 이 함수는 Grouping 타입의 인스턴스를 반환합니다. Grouping 인스턴스는 모든 그룹에 연산을 지연(lazy) 방식으로 적용할 수 있게 해 줘요. 그룹은 실제로 연산이 실행되기 직전에 만들어집니다.

구체적으로 Grouping은 다음 연산을 지원해요.

  • eachCount()는 각 그룹의 요소 수를 세요.
  • fold()reduce()는 각 그룹을 별도 컬렉션으로 취급해 fold와 reduce 연산을 수행하고 결과를 반환해요.
  • aggregate()는 주어진 연산을 각 그룹의 모든 요소에 차례로 적용하고 결과를 반환해요. 이는 Grouping에 어떤 연산이든 수행하는 일반적인 방법입니다. fold나 reduce로 충분하지 않을 때 커스텀 연산을 구현하려면 이것을 사용해요.

groupingBy() 함수가 만든 그룹들을 순회하려면 결과 Mapfor 연산자를 사용할 수 있어요. 이렇게 하면 각 키와 그 키에 연결된 요소 수에 접근할 수 있습니다.

다음 예시는 groupingBy() 함수로 문자열을 첫 글자별로 그룹화하고, 각 그룹의 요소 수를 센 다음, 각 그룹을 순회해 키와 요소 수를 출력하는 방법을 보여줘요.

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four", "five")

    // Groups the strings by their first letter using groupingBy() and counts the elements in each group
    val grouped = numbers.groupingBy { it.first() }.eachCount()

    // Iterates through each group and prints the key and its associated values
    for ((key, count) in grouped) {
        println("Key: $key, Count: $count")
        // Key: o, Count: 1
        // Key: t, Count: 2
        // Key: f, Count: 2
    }
//sampleEnd
}

더 알아보기 (Learn more)