# In-place sort for IntArray

**URL:** <https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830>\
**Category:** Support\
**Created:** [March 24, 2020, 9:07pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830 "2020-03-24T21:07:30Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sargon](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@Sargon](https://discuss.kotlinlang.org/u/Sargon)\
**Post date:** [March 24, 2020, 9:07pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/1 "2020-03-24T21:07:30Z")

</div>

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:

If the `IntArray` contains `1, 2, 3` and

```auto
weight[1] = 10
weight[2] = 42
weight[3] = 5

```

the sorted array should contain `2, 1, 3`.

Thanks! 🙂

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [March 24, 2020, 9:59pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/2 "2020-03-24T21:59:21Z")

</div>

do you mean something like:

```run-kotlin
inline fun printIntArrayContent(lamb : () -> IntArray){
    println(lamb().contentToString())
}
fun main() = printIntArrayContent{
//sampleStart
    arrayOf(1,2,3)
        .zip(arrayOf(10, 42, 5))
        .sortedByDescending { it.second }
        .map { it.first }
        .toIntArray()
//sampleEnd
}

```

But with better performance?

---

<div class="post-metadata">

**Author:** ![Sargon](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@Sargon](https://discuss.kotlinlang.org/u/Sargon)\
**Post date:** [March 24, 2020, 10:07pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/3 "2020-03-24T22:07:37Z")

</div>

Yes, with _much_ better performance. 😛  
Something like:

```auto
var numbers: IntArray = intArrayOf(1, 2, 3)
numbers.sortWith(Comparator { a: Int, b: Int -> weight[b] - weight[a] } )

```

---

<div class="post-metadata">

**Author:** ![madmax1028](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/madmax1028/32/3335_2.png) [@madmax1028](https://discuss.kotlinlang.org/u/madmax1028)\
**Post date:** [March 24, 2020, 10:42pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/5 "2020-03-24T22:42:02Z")

</div>

Maybe, but this can also cause `ArrayIndexOutOfBoundsException` 😉

My proposition is this:

```kotlin
fun main() {
	val sortedSet = sortedSetOf(
		compareByDescending { it.second },
		1 to 10,
		2 to 42,
		3 to 5
	)
	println(sortedSet.map { it.first }) // [2, 1, 3]
}

```

---

<div class="post-metadata">

**Author:** ![wdoker](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wdoker/32/4748_2.png) [@wdoker](https://discuss.kotlinlang.org/u/wdoker)\
**Post date:** [March 26, 2020, 1:29pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/6 "2020-03-26T13:29:01Z")

</div>

JDK implements in-place sorting via [DualPivotQuicksort](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/DualPivotQuicksort.java)

There is no such version available for custom comparator.

I guess you can use a 3rd-party like [fastutil quickSort](http://fastutil.di.unimi.it/docs/it/unimi/dsi/fastutil/ints/IntArrays.html#quickSort(int%5B%5D,int,int,it.unimi.dsi.fastutil.ints.IntComparator))

---

<div class="post-metadata">

**Author:** ![lrouquette](https://avatars.discourse-cdn.com/v4/letter/l/d6d6ee/32.png) [@lrouquette](https://discuss.kotlinlang.org/u/lrouquette)\
**Post date:** [March 27, 2020, 4:33pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/7 "2020-03-27T16:33:47Z")

</div>

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)
}

```

---

<div class="post-metadata">

**Author:** ![elizarov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/elizarov/32/2164_2.png) [@elizarov](https://discuss.kotlinlang.org/u/elizarov)\
**Post date:** [March 30, 2020, 8:27am UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/8 "2020-03-30T08:27:12Z")

</div>

> [@Sargon](#):
>
> 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?

Here is your request: [https://youtrack.jetbrains.com/issue/KT-37860](https://youtrack.jetbrains.com/issue/KT-37860)

Btw, do you care about guaranteed O(n log n) performance for your use-case or an average O(n log n) performance (as with quick sort) is fine?

---

<div class="post-metadata">

**Author:** ![Sargon](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@Sargon](https://discuss.kotlinlang.org/u/Sargon)\
**Post date:** [April 2, 2020, 4:56pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/9 "2020-04-02T16:56:18Z")

</div>

> [@elizarov](#):
>
> [snipped]
> 
> Here is your request: [https://youtrack.jetbrains.com/issue/KT-37860](https://youtrack.jetbrains.com/issue/KT-37860)
> 
> Btw, do you care about guaranteed O(n log n) performance for your use-case or an average O(n log n) performance (as with quick sort) is fine?

Thanks for creating the feature request!

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.

---

<div class="post-metadata">

**Author:** ![lrouquette](https://avatars.discourse-cdn.com/v4/letter/l/d6d6ee/32.png) [@lrouquette](https://discuss.kotlinlang.org/u/lrouquette)\
**Post date:** [April 3, 2020, 4:56pm UTC](https://discuss.kotlinlang.org/t/in-place-sort-for-intarray/16830/10 "2020-04-03T16:56:39Z")

</div>

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.
