A collections question: Say I have a list of Pair...
# announcements
p
A collections question: Say I have a list of Pairs, where first is a description, and second is a userid. How do I easily sort the list in the following order: a) all entries where second = "SYSTEM" ordered by description b) all entries where second = a particular value (e.g. the logged in user) c) all the remaining entries (second not SYSTEM or the logged in user) I don't think I can use a straight comparator as one of the values (the user) used for sorting is variable
a
You’d have to rebuild the comparator each time, rather than having a constant, yes. Aim to make a
fun sortForUser(username:String):Comparator<Pair<String, String>>
which ranks by the second properties
p
Ta, so basically create a filtered sorted list of a) create a filtered sorted list of b) create a filtered sorted list of c) And combine them ?
a
well, I think you can still do it in one go by combining a comparator that does the partitioning with a comparator that sorts by description
👍 1
p
Gotcha, cheers
d
it'll probably be a big if-else chain... comparators like this are ugly beasts
a
sth like this:
Copy code
@Test
    fun scratchpad() {
        val sortByDescription = compareBy<Pair<String, String>> { it.first }
        fun rankUser(username: String): Comparator<String> {
            return compareBy<String> {
                when (it) {
                    "SYSTEM" -> 0
                    username -> 1
                    else -> 2
                }
            }
        }

        fun sortForUser(username: String): Comparator<Pair<String, String>> {
            return compareBy(rankUser(username)) { it.second }
        }

        val example = listOf("red" to "xyzzy", "orange" to "SYSTEM", "blue" to "SYSTEM", "green" to "other")
        assertEquals(
            listOf("blue" to "SYSTEM", "orange" to "SYSTEM", "red" to "xyzzy", "green" to "other"),
            example.sortedWith(sortForUser("xyzzy").then(sortByDescription))
        )
        assertEquals(
            listOf("blue" to "SYSTEM", "orange" to "SYSTEM", "green" to "other", "red" to "xyzzy"),
            example.sortedWith(sortForUser("other").then(sortByDescription))
        )
    }
The default/factory methods on Comparator in Java8 made a huge difference in writing them, I still don’t feel familiar with the Kotlin equivalents yet though (
compareBy
and
.then
here)
d
Your code does not quite meet the stated requirements, as it always sorts by description. Which the requirements state should only happen in case a
a
ah,
then
is an infix function, that looks nicer. It’s just a quick draft 🙂
@diesieben07 I think that’s also achievable (if actually desired, and not just a fuzzy spec) by adapting the
sortByDescription
to delegate/return 0 based on the user. At least, that’s my understanding of the stable sort
d
hm. maybe 😄
j
Although this is solvable using a combination of sorting algorithms (i.e. introduce a synthetic field and then use Java 8
Comparator
interface (see
thenComparing
), I would advise that the domain model probably needs restructuring especially if this is not a one-off use case.