https://kotlinlang.org logo
Title
v

voddan

03/05/2019, 11:47 AM
What's the cleanest way to test if all elements in a list are distinct? The best I could come up with was
list.size == list.distinct().size
, which is efficient, but ugly
☝️ 1
h

hho

03/05/2019, 12:16 PM
Unless the list in question is huge this is the best solution. I don't think it's that ugly, either – just put it in an extension:
fun Collection<*> allDistinct(): Boolean = this.size == this.distinct().size
s

sitepodmatt

03/05/2019, 12:19 PM
distinct converts it to a mutableset then toList()
which should be fine, but if the list is large then you false-fast when you find the first duplicate
fun <T> List<T>.isDistinct() = this.fold(mutableMapOf<T,Int>()) { acc, i ->
    acc.also {
        it[i] = ((it[i] ?: 0) + 1).also { count ->
            if(count > 1) {
                return false
            }
        }
    }
}.let { true }
you would have to benchmark to see if there was any real performance gains to be had
if its sorted there much quicker ways as you only have to compare the previous element
m

marstran

03/05/2019, 12:57 PM
Could also go for a procedural approach that stops immediately when it finds a duplicate:
fun <T> List<T>.isDistinct(): Boolean {
    val mutSet = mutableSetOf<T>()
    for (elem in this) {
        if (elem in mutSet) {
            return false
        }
        mutSet.add(elem)
    }
    return true
}
p

Pavlo Liapota

03/05/2019, 1:09 PM
Or just
fun <T> List<T>.isDistinct(): Boolean {
    val mutSet = mutableSetOf<T>()
    return all { mutSet.add(it) }
}
3
v

voddan

03/05/2019, 1:23 PM
Nice optimizations! Feels like such a method could be in the stdlib. Do you think I should open an issue?
Here is the issue https://youtrack.jetbrains.com/issue/KT-30270 @Pavlo Liapota I hope you don't mind I posted your code there
👍 1