(novato de Kotlin aquí) Tengo un archivo de texto con filas que se ven así:
1-1-1 1-1-2 1-1-3 2-1-1 2-1-2 etc.Tengo que transformar estos datos en un mapa donde la clave son los 2 primeros elementos y el valor es una lista de los terceros elementos que coinciden con la clave. Por ejemplo, los registros anteriores se transformarán en este JSON:
1-1: [1, 2, 3] 2-1: [1, 2] etc.No puedo incrementar la lista. Aquí hay una versión simplificada, me quedo atascado en el "else":
fun main () { val l1 = mutableListOf("1-1-1", "1-1-2", "1-1-3", "2-1-1", "2-1-2") val m = mutableMapOf<String, List<Int>>() for (e in l1) { val c = e.split("-") val key = "${c[0]}-${c[1]}" if (m[key] == null) m[key] = listOf(c[2].toInt()) else println("How do I append to the list?") } println(m) }Producción:
{1-1=[1], 2-1=[1]}Pero yo quiero:
{1-1=[1, 2, 3], 2-1=[1, 2]}Gracias (¡los comentarios sobre la forma idiomática son bienvenidos!)
Si seguimos con tu estrategia, lo que necesitas es que el tipo de valor sea MutableList. Luego, puede agregar a MutableList existente cuando ya haya una lista existente para esa clave:
fun main() { val l1 = mutableListOf("1-1-1", "1-1-2", "1-1-3", "2-1-1", "2-1-2") val m = mutableMapOf<String, MutableList<Int>>() for (e in l1) { val c = e.split("-") val key = "${c[0]}-${c[1]}" if (m[key] == null) m[key] = mutableListOf(c[2].toInt()) else m[key]!!.add(c[2].toInt()) } println(m) } Esto puede ser más natural usando getOrPut() . Devuelve el MutableList existente o crea uno y lo coloca en el mapa si falta. Entonces no tenemos que lidiar con if/else, y simplemente podemos agregar el nuevo elemento a la lista.
fun main() { val l1 = mutableListOf("1-1-1", "1-1-2", "1-1-3", "2-1-1", "2-1-2") val m = mutableMapOf<String, MutableList<Int>>() for (e in l1) { val c = e.split("-") val key = "${c[0]}-${c[1]}" m.getOrPut(key, ::mutableListOf).add(c[2].toInt()) } println(m) } Pero podemos usar las funciones map y groupBy para crearlo de forma más sencilla:
val m = l1.map { it.split("-") } .groupBy( { "${it[0]}-${it[1]}" }, // keys { it[2].toInt() } // values )Puede lograr el resultado deseado con una sola llamada a groupBy de la biblioteca estándar de Kotlin.
val input = listOf("1-1-1", "1-1-2", "1-1-3", "2-1-1", "2-1-2") val result = input.groupBy( { it.substringBeforeLast("-") }, // extract key from item { it.substringAfterLast("-").toInt() } // extract value from item )La primera función lambda extrae la clave para agrupar por cada elemento de la lista. La segunda función lambda proporciona el valor a usar para cada elemento de la lista.
También puede hacerlo asignando primero sus valores a Pair y luego agrupándolos de la siguiente manera:
fun main(args: Array<String>) { val input = listOf("1-1-1", "1-1-2", "1-1-3", "2-1-1", "2-1-2") val result = input.map { val values = it.split("-") "${values[0]}-${values[1]}" to values[2] }.groupBy ({ it.first }) { it.second } println(result) }