https://kotlinlang.org logo
Title
a

arturro

07/10/2017, 12:09 PM
Hi Guys! is there a more clean-kotlin-way to write this code:
if (v1 == null && v2 == null) {
            return 0
        }
        if (v1 != null && v2 == null) {
            return 1
        }
        if (v1 == null && v2 != null) {
            return -1
        }
d

diesieben07

07/10/2017, 12:11 PM
arturro: Is that in a Comparator?
a

arturro

07/10/2017, 12:15 PM
yes
It looks like this:
override fun compare(o1: T, o2: T): Int {
        val property = o1.javaClass.kotlin.declaredMemberProperties.first { it -> it.name == propertyName }

        val v1 = property.get(o1) as? Comparable<Any>
        val v2 = property.get(o2) as? Comparable<Any>

        if (v1 == null && v2 == null) {
            return 0
        }
        if (v1 != null && v2 == null) {
            return 1
        }
        if (v1 == null && v2 != null) {
            return -1
        }
        return v1!!.compareTo(v2!!)
    }
d

diesieben07

07/10/2017, 12:17 PM
You could just do
val c = compareBy(MyClass::property)
a

arturro

07/10/2017, 12:18 PM
I dont know the property
I know it only at runtime, as a string name
d

diesieben07

07/10/2017, 12:18 PM
Then you look it up using reflection and then pass it to
compareBy
.
And then you can use
nullsLast
resp.
nullsFirst
to allow nulls.
a

arturro

07/10/2017, 12:28 PM
I am not sure how to do this. Now I have:
fun <T : Any> List<T>.sortByProperty(propertyName: String, asc: Boolean = true) : List<T> {
    val field = ???
    return this.sortedBy { field }
}
But it does'n compile.
d

diesieben07

07/10/2017, 12:36 PM
T
would have to be reified so you can get it's class. Then you can use T::class to look up the property
propertyName
should really not be a string though..
c

cedric

07/10/2017, 12:48 PM
Do not use reflection in a comparator
a

arturro

07/10/2017, 12:50 PM
I have to 🙂
c

cedric

07/10/2017, 12:51 PM
Then at least don't do so for every call of
compare
a

arturro

07/10/2017, 12:51 PM
Now I have something like this:
inline fun <reified T : Any> List<T>.sortByPropertyName(propertyName: String) : List<T> {
    val prop = T::class.declaredMemberProperties.first { it.name == propertyName }
    return this.sortedBy { prop }
}
But it doesn't compile, the error is:
Error:(11, 17) Kotlin: Type parameter bound for R in inline fun <T, R : Comparable<R>> Iterable<T>.sortedBy(crossinline selector: (T) -> R?): List<T>
 is not satisfied: inferred type KProperty1<T, *> is not a subtype of Comparable<KProperty1<T, *>>
Any suggestion how to fix it are welcome 🙂
c

cedric

07/10/2017, 2:07 PM
@artur
prop
itself does not implement
Comparable
, you need code in there that can be mapped by the compiler to a
Comparable
e.g.
return this.sortedBy { -1 }
(obviously not what you want but you get the idea)
a

artur

07/10/2017, 2:19 PM
Thks Cédric!