mama
mama

Reputation: 2227

Is it possible to sort each group in groupBy in a simple way?

I have a function which groups my highscore list into groups for each category, but when I get the groups, they are not in order anymore and the person with the highest score, is placed some random place in the list.

I was wondering if there is a simple way I can just sort each group.

My grouping function looks like this:

private fun getCategories(scores: List<HighScore>): List<Pair<String, List<HighScore>>> {
    return scores.groupBy {
        it.word.category
    }.toList()
}

My model looks like this


data class HighScore(
    val ID: String?,
    val player: String,
    val time: Int,
    val hints: Int,
    val wrongs: Int,
    val word: Word
) {
    fun getScore():Int {
        return time*word.difficulty/hints/(wrongs+1)
    }
}

and my old sorting function looks like this (but i guess I could just use sortedByDescending()

private fun order(scores: ArrayList<HighScore>): List<HighScore> {
    scores
        .sortWith(kotlin.Comparator { lhs, rhs ->
            when {
                lhs.getScore() > rhs.getScore() -> -1
                lhs.getScore() < rhs.getScore() -> 1
                else -> 0
            }
        })

    return if (scores.size > 10) {
        scores.slice(0 until 10)
    } else {
        scores
    }
}

Thanks in advance :-)

Upvotes: 1

Views: 1360

Answers (1)

Eduard Tomek
Eduard Tomek

Reputation: 374

You can improve your function to something like this:

    private fun getCategories(scores: List<HighScore>): List<Pair<String, List<HighScore>>> {
        return scores
            .sortedByDescending { it.getScore() }
            .groupBy { it.word.category }
            .mapValues { it.value.take(10) }
            .map { Pair(it.key, it.value) }
    }

It may be even simpler if you use just Map<String, List<HighScore>> instead of List<Pair<String, List<HighScore>>> as your return type:

    private fun getCategories(scores: List<HighScore>): Map<String, List<HighScore>> {
        return scores
            .sortedByDescending { it.getScore() }
            .groupBy { it.word.category }
            .mapValues { it.value.take(10) }
    }

You can now pass your List<HighScore> in any order in the function and it will always return high scores grouped by category, sorted from the highest and each group will have at most 10 elements.

Upvotes: 2

Related Questions