Implementing a groupBy extension for Kotlin Flow

Viewed 226

I have a flow like this: Flow<List<Transaction>>

Each Transaction object has a Category object

What i want is an extension function that groups the transactions per Category

This is what i've tried:

inline fun <T, K> Flow<Iterable<T>>.groupIterableBy(crossinline keySelector: (T) -> K): Flow<Map<K, MutableList<T>>> = map {
        val storage = HashMap<K, MutableList<T>>()
        it.map{ element ->
            val key = keySelector(element)
            if (storage[key] == null){
                storage[key] = mutableListOf()
            }
            storage[key]!!.add(element)
        }
        return@map storage
}

This works great, but i don't feel like this is programmed in a clean way. Does anyone have suggestions for making this function cleaner?

1 Answers

Following IR42's comment, this should work. Why not use

Iterable.groupBy()

Example scratch:

data class Tra(
    val cat: Cat
)

data class Cat(
    val name: String
)

val flow = flowOf(
    listOf(
        Tra(Cat("A")),
        Tra(Cat("B")),
        Tra(Cat("D")),
        Tra(Cat("B"))
    ),
    listOf(
        Tra(Cat("A")),
        Tra(Cat("C")),
        Tra(Cat("B")),
        Tra(Cat("A")),
        Tra(Cat("C"))
    )
)

inline fun <T, K> Flow<Iterable<T>>.groupIterableBy(crossinline  keySelector: (T) -> K): Flow<Map<K, List<T>>> =
    map { it.groupBy(keySelector) }

val groupedFlow = flow.groupIterableBy{it.cat.name}

runBlocking {
    groupedFlow
        .collect {
            println(it)
        }
}

It prints:

{A=[Tra(cat=Cat(name=A))], B=[Tra(cat=Cat(name=B)), Tra(cat=Cat(name=B))], D=[Tra(cat=Cat(name=D))]}
{A=[Tra(cat=Cat(name=A)), Tra(cat=Cat(name=A))], C=[Tra(cat=Cat(name=C)), Tra(cat=Cat(name=C))], B=[Tra(cat=Cat(name=B))]}

Is this the result you're looking for?

Related