Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting Secondary Collection using Primary Sorted Collection's field

I have an unsorted List of Users and a sorted list of Users id. Id is a string. I want to sort first list by second. How to do that in Kotlin?

data class User(val name : String, val id : String)

val unsorted = listOf<User>(
    User("Max", "b12s11"),
    User("Joe", "dj1232"),
    User("Sam", "23d112"),
    User("Tom", "k213i1")
)

val sorted = listOf<String>(
    "dj1232",
    "b12s11",
    "k213i1",
    "23d112"
)

//  what I need
val result = listOf<User>(
    User("Joe", "dj1232"),
    User("Max", "b12s11"),
    User("Tom", "k213i1"),
    User("Sam", "23d112")
)
like image 382
hasterix Avatar asked Oct 01 '19 07:10

hasterix


3 Answers

Shorter solution:

val result = unsorted.sortedBy { sorted.indexOf(it.id) }
like image 158
Andrei Tanana Avatar answered Nov 15 '22 10:11

Andrei Tanana


Although the other answers show a solution to your problem, it seems to me that a Map<String, User> might better fit the purpose, e.g.:

val usersByid = unsorted.associateBy { it.id }

val result = sorted.mapNotNull {
  usersById[it]
}

I assume that every id is only once in the list, therefore I used associateBy. Otherwise it wouldn't be an id for me ;-)

The main difference between this solution and others is that this solution only returns the entries that are also in the sorted-list. Note that if you have users for which you have no id in the sorted-list, this solution omits them, whereas other solutions put those entries at the front of the list. Depends on what you really want.

It could be that this solution is more efficient than the others. Accessing the Map should be much faster then reiterating all the entries over and over again (which both indexOf and first basically do).

like image 40
Roland Avatar answered Nov 15 '22 10:11

Roland


I don't know of any Kotlin syntax for doing this, sorting one list by another, but this solution should work for you (the way I understood this question, was that you want to sort according to the Id's in sorted):

 val correctList = arrayListOf<User>()

    sorted.forEach { sortedId ->

        correctList.add(unsorted.first {
            it.id == sortedId
        })
    }

It iterates over your sorted list of Id's and takes the item in the first list (unsorted) which matches that ID and adds it to correctList


Edit: see answer from @Andrei Tanana for a better kotlin answer than mine : sort unsorted collection with another sorted collection's field it's pretty cool :D


Edit2: Thanks to @Roland for pointing out, I can simplify my answer even further with :

val correctList = sorted.map { sortedId -> unsorted.first { it.id == sortedId } }
like image 2
a_local_nobody Avatar answered Nov 15 '22 08:11

a_local_nobody