Iterable.groupingBy în Kotlin

Pregătește o grupare după cheie; eachCount() numără apoi câte elemente are fiecare cheie (frecvența).

Sintaxă
fun <T, K> Iterable<T>.groupingBy(cheie: (T) -> K): Grouping<T, K>
fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int>
fun <T, K, R> Grouping<T, K>.fold(initial: R, operatie: (acc: R, T) -> R): Map<K, R>

Ce face Iterable.groupingBy

groupingBy { ... } nu calculează nimic singur: întoarce un obiect Grouping, care ține minte colecția și funcția-cheie. Pe el apelezi o operație care se face pe fiecare grupă: eachCount(), fold, reduce sau aggregate.

eachCount() întoarce un Map<K, Int>: de câte ori apare fiecare cheie. Este modul obișnuit de a număra frecvențe (cuvinte, voturi, note). Spre deosebire de groupBy, nu se creează liste cu elementele.

Parametri

Parametru Descriere
cheie Funcția care dă cheia (grupa) fiecărui element.

Ce returnează

groupingBy: un Grouping<T, K>. eachCount: un Map<K, Int> cu numărul de elemente pe cheie.

Exemple

Exemplul 1: Numărarea voturilor

Cheia este chiar votul (it). Cheile apar în ordinea primei întâlniri.

fun main() {
    val voturi = listOf("Ana", "Ion", "Ana", "Maria", "Ana", "Ion")
    val rezultat = voturi.groupingBy { it }.eachCount()
    println(rezultat)

    val castigator = rezultat.maxBy { it.value }
    println("Câștigă ${castigator.key} cu ${castigator.value} voturi")
}

Rezultat

{Ana=3, Ion=2, Maria=1}
Câștigă Ana cu 3 voturi

Exemplul 2: Frecvența literelor într-un cuvânt

Un String se poate parcurge ca o colecție de caractere, deci are și el groupingBy.

fun main() {
    val cuvant = "abracadabra"
    println(cuvant.groupingBy { it }.eachCount())
}

Rezultat

{a=5, b=2, r=2, c=1, d=1}

Exemplul 3: Total pe categorie cu fold

Pe un Grouping putem face și fold: pentru fiecare categorie pornim de la 0 și adunăm sumele cheltuite.

data class Cheltuiala(val categorie: String, val lei: Int)

fun main() {
    val luna = listOf(
        Cheltuiala("mâncare", 120), Cheltuiala("transport", 40),
        Cheltuiala("mâncare", 85), Cheltuiala("distracție", 60), Cheltuiala("transport", 25),
    )
    val totaluri = luna.groupingBy { it.categorie }.fold(0) { acc, c -> acc + c.lei }
    println(totaluri)
}

Rezultat

{mâncare=205, transport=65, distracție=60}

Greșeli frecvente

  • Afișezi direct rezultatul lui groupingBy: vezi doar numele unui obiect intern. Trebuie apelată o operație, de exemplu eachCount().
  • Scrii groupBy { it }.mapValues { it.value.size }: merge, dar creează liste inutile. groupingBy { it }.eachCount() numără direct.

Comenzi înrudite

  • Iterable.groupBy: Împarte elementele în grupe după o cheie și întoarce un map: cheie → lista elementelor din acea grupă.
  • Iterable.count: Numără elementele colecției sau doar pe cele care îndeplinesc o condiție.
  • Iterable.fold: Pornește de la o valoare inițială și o combină pe rând cu fiecare element, întorcând rezultatul final.
  • Map.maxByOrNull: Găsește intrarea (cheie și valoare) pentru care funcția dată are valoarea maximă; null dacă map-ul e gol.