Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fold pairs into map of set; create map entries if not existing already

Tags:

kotlin

using a list of pairs, want to transform them to a map of sets.

input: list of pairs is like this

listOf(Pair('bob', UGLY), Pair('sue', PETTY), Pair('bob', FAT))

desired output is a map of set where the key is first of pair, and the set is the second

mapOf('bob' to setOf(UGLY, FAT), 'sue' to setOf(PETTY))

I have tried this, but wow this is incredibly verbose. can this be reduced?

fun main(args: Array<String>) {
    var m = HashMap<Int, MutableSet<Int>>()
    listOf(1 to 1, 2 to 2, 1 to 3).map {
        val set = m.getOrPut(it.first, { listOf<Int>().toMutableSet() })
        set.add(it.second)
        set
    }
    println (m)
}
-> {1=[1, 3], 2=[2]}

// yet another version, yields the correct result, but I feel a lack of clarity 
// that maybe I'm missing a library function that would suit the purpose.
listOf(1 to 1, 2 to 2, 1 to 3).fold(m, {
    mapSet, pair ->
    val set = mapSet.getOrPut(pair.first, { listOf<Int>().toMutableSet() })
    set.add(pair.second)
    mapSet
})
-> {1=[1, 3], 2=[2]}
like image 308
activedecay Avatar asked Jan 20 '16 04:01

activedecay


1 Answers

You can use groupBy and then a mapValues like this:

fun main(args: Array<String>) {
    val pairs = listOf(Pair("bob", "UGLY"), Pair("sue", "PETTY"), Pair("bob", "FAT"))
    val result = pairs
            .groupBy { it.first }
            .mapValues { it.value.map { p -> p.second }.toSet() }
    println(result)
}
like image 71
marcospereira Avatar answered Oct 21 '22 04:10

marcospereira