kotlinintermediate

Map Operations — Transform, Merge, Group

Advanced map operations: groupBy, associate, flatMap, merge strategies, and map transformations.

kotlin
data class Employee(val name: String, val dept: String, val salary: Int)

fun main() {
    val employees = listOf(
        Employee("Alice", "Engineering", 120_000),
        Employee("Bob", "Engineering", 110_000),
        Employee("Charlie", "Marketing", 90_000),
        Employee("Diana", "Marketing", 95_000),
        Employee("Eve", "Engineering", 130_000),
        Employee("Frank", "Sales", 85_000)
    )

    // groupBy
    val byDept = employees.groupBy { it.dept }
    byDept.forEach { (dept, emps) ->
        println("$dept: ${emps.map { it.name }}")
    }

    // groupBy with value transform
    val namesByDept = employees.groupBy({ it.dept }, { it.name })
    println("\nNames by dept: $namesByDept")

    // associate / associateBy
    val byName = employees.associateBy { it.name }
    println("\nAlice: ${byName["Alice"]}")

    val nameSalary = employees.associate { it.name to it.salary }
    println("Salaries: $nameSalary")

    // Aggregations
    val avgSalaryByDept = employees
        .groupBy { it.dept }
        .mapValues { (_, emps) -> emps.map { it.salary }.average() }
    println("\nAvg salary: $avgSalaryByDept")

    val maxSalaryByDept = employees
        .groupBy { it.dept }
        .mapValues { (_, emps) -> emps.maxOf { it.salary } }
    println("Max salary: $maxSalaryByDept")

    // Map transformations
    val config = mapOf("host" to "localhost", "port" to "8080", "debug" to "true")

    // mapKeys / mapValues
    val upperConfig = config.mapKeys { (k, _) -> k.uppercase() }
    println("\nUpper keys: $upperConfig")

    // filterKeys / filterValues
    val numericConfig = config.filterValues { it.toIntOrNull() != null }
    println("Numeric: $numericConfig")

    // Merge two maps
    val defaults = mapOf("host" to "0.0.0.0", "port" to "3000", "env" to "production")
    val overrides = mapOf("port" to "8080", "debug" to "true")
    val merged = defaults + overrides
    println("\nMerged: $merged")

    // Custom merge
    fun <K, V> Map<K, V>.mergeWith(
        other: Map<K, V>,
        resolve: (V, V) -> V
    ): Map<K, V> = buildMap {
        putAll(this@mergeWith)
        other.forEach { (k, v) ->
            put(k, this[k]?.let { resolve(it, v) } ?: v)
        }
    }

    val counts1 = mapOf("a" to 1, "b" to 2, "c" to 3)
    val counts2 = mapOf("b" to 5, "c" to 1, "d" to 4)
    val summed = counts1.mergeWith(counts2) { a, b -> a + b }
    println("Summed: $summed")

    // flatMap on map entries
    val tags = mapOf(
        "kotlin" to listOf("jvm", "multiplatform"),
        "swift" to listOf("ios", "macos"),
        "dart" to listOf("flutter", "web")
    )
    val allPlatforms = tags.flatMap { (lang, platforms) ->
        platforms.map { "$lang/$it" }
    }
    println("\nPlatforms: $allPlatforms")

    // getOrDefault / getOrElse
    val settings = mapOf("theme" to "dark")
    val theme = settings.getOrDefault("theme", "light")
    val fontSize = settings.getOrElse("fontSize") { "14" }
    println("\nTheme: $theme, Font: $fontSize")

    // Counting occurrences
    val words = "the quick brown fox jumps over the lazy fox".split(" ")
    val frequency = words.groupingBy { it }.eachCount()
    println("\nFrequency: $frequency")

    // Partition map
    val (highPaid, others) = employees.partition { it.salary > 100_000 }
    println("\nHigh paid: ${highPaid.map { it.name }}")
    println("Others: ${others.map { it.name }}")
}

Use Cases

  • Data aggregation and grouping
  • Configuration merging strategies
  • Frequency counting and analysis

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.