I’m trying to sort an IntArray based on a comparator and noticed there is no way to do this in-place (no “sortWith” function). Am I missing something obvious here?
Edit: I don’t the numbers to be sorted directly, but based on some weight-lookup:
Simple solution. It can be used with a Comparator, or you can create the same function with a comparison function (Int, Int) -> Int.
fun main() {
val indices = intArrayOf(1, 2, 3)
val weight = IntArray(4)
weight[1] = 10
weight[2] = 42
weight[3] = 5
indices.sortWith(Comparator<Int> { a, b -> weight[b] - weight[a] })
println(indices.contentToString())
}
fun IntArray.sortWith(comparator: Comparator<Int>) {
// Code from https://en.wikipedia.org/wiki/Quicksort
fun partition(array: IntArray, lo: Int, hi: Int): Int {
val pivot = array[(lo + hi) / 2]
var i = lo - 1
var j = hi + 1
while (true) {
do {
i = i + 1
} while (comparator.compare(array[i], pivot) < 0)
do {
j = j - 1
} while (comparator.compare(array[j], pivot) > 0)
if (i >= j) {
return j
}
val tmp = array[j]
array[j] = array[i]
array[i] = tmp
}
}
fun quicksort(array: IntArray, lo: Int, hi: Int) {
if (lo < hi) {
val p = partition(array, lo, hi)
quicksort(array, lo, p)
quicksort(array, p + 1, hi)
}
}
quicksort(this, 0, this.size - 1)
}
For my use-case (development of 2-player board games) an average O(n log n) would be perfectly fine.
But if what Ilya Gorbunov has commented in the issue (“memory inefficient as it would require to box the elements being compared each time”), that would be a reason in my opinion to not implement this feature - at least not as long as the JVM requires this.
You don’t need boxing if you create a specific interface like IntComparator in the fastutil library. But I don’t know if a comparison function like (Int, Int) → Int will box the values or not.