Kotlin - Sort List by using formatted date string (functional)

19,525

Solution 1

More than one approach can be used. It depends on how you process after you get the sorted result.

Points to note:

  • java.time.LocalDateTime has already implemented java.lang.Comparable<T> Interface. We can use the kotlin stdlib List.sortBy to sort the List<LocalDateTime> directly.

Ref:

// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-by.html
fun <T, R : Comparable<R>> Iterable<T>.sortedBy(
    selector: (T) -> R?
): List<T>

The easiest way is to transform the String -> java.time.LocalDateTime and use the List.sortBy directly.

The whole implementation could be like this:

 import java.time.LocalDateTime
 import java.time.format.DateTimeFormatter

 ...


// Create a convert function, String -> LocalDateTime
val dateTimeStrToLocalDateTime: (String) -> LocalDateTime = {
    LocalDateTime.parse(it, DateTimeFormatter.ofPattern("dd-MM-yyyy | HH:mm"))
}

val list = listOf("14-10-2016 | 15:48",
        "01-08-2015 | 09:29",
        "15-11-2016 | 19:43")

// You will get List<LocalDateTime> sorted in ascending order
list.map(dateTimeStrToLocalDateTime).sorted()

// You will get List<LocalDateTime> sorted in descending order
list.map(dateTimeStrToLocalDateTime).sortedDescending()

// You will get List<String> which is sorted in ascending order
list.sortedBy(dateTimeStrToLocalDateTime)

// You will get List<String> which is sorted in descending order
list.sortedByDescending(dateTimeStrToLocalDateTime)

If you want to use org.joda.time.DateTime, you can just make a tiny change on the convert function.

A friendly reminder, always pick val as your first choice in Kotlin :).

Solution 2

Another alternative to the excellent Saravana answer (for minimalist and compact freaks like me..) is:

val cmp = compareBy<String> { LocalDateTime.parse(it, DateTimeFormatter.ofPattern("dd-MM-yyyy | HH:mm")) }

list.sortedWith(cmp).forEach(::println)

01-08-2015 | 09:29
14-10-2016 | 15:48
15-11-2016 | 19:43

Ps: it is the default variable for single inputs

Share:
19,525

Related videos on Youtube

Ivar Reukers
Author by

Ivar Reukers

Software Developer based in the Netherlands

Updated on June 18, 2022

Comments

  • Ivar Reukers
    Ivar Reukers almost 2 years

    I'm trying to create a Kotlin REST API, which retrieves values from a PostgreSQL database. Now the values in these results are f.e. "14-10-2016 | 15:48" and "01-08-2015 | 09:29" So the syntax basically is dd-MM-yyyy | hh:mm

    Now what I'm trying to do is create a function that will order them by date placed. (Assume these strings are in an array)

    var list = listOf("14-10-2016 | 15:48",
                      "01-08-2015 | 09:29",
                      "15-11-2016 | 19:43")
    

    What would be the cleanest (and most functional) way of sorting these? (so f.e. is there a way where I don't have to take substrings of the day, month, etc. cast them to an Int, compare them in a nested loop and write the results to a different array? (that's the only way I could think of).

  • Egor
    Egor over 7 years
    Not sure Kotlin is compatible with Java 8, but anyway, I guess the OP was looking for a solution written in Kotlin.
  • Jayson Minard
    Jayson Minard over 7 years
    instead of using map to print, maybe use list.sortedWith(cmp).forEach(::println)
  • Saravana
    Saravana over 7 years
    @Egor sorry, I know Java only but the logic would be similar to the answer I posted
  • Gary LO
    Gary LO over 7 years
    @elect Immutable objects are always easier to trace and can be used in mutli-threaded environment without any worries. Most of the time you won't need var in Kotlin if you are familiar with functional approach. But var is more memory efficient, use it wisely to take the only benefit.
  • karthik prasad
    karthik prasad about 6 years
    Call requires API level 26 though. Any backward compatible solutions?