'Rotate kotlin array

Assume that I have an array like 1 2 3 4 5, I want to rotate it to the left by n and get a new one.

For example the 2 rotation of the above array will result in 3 4 5 1 2. I didn't found any extension function to do that.



Solution 1:[1]

You can use built-in java Collections.rotate method, but you need to convert your array to list firstly:

val arr = intArrayOf(1, 2, 3, 4, 5)
val list = arr.toList()
Collections.rotate(list, -2)
println(list.toIntArray().joinToString())

Outputs

3, 4, 5, 1, 2

Solution 2:[2]

I interpret "get a new one" to mean that the extension function should return a new array instance, like so (boundary checks omitted, sliceArray is an stdlib function) :

fun <T> Array<T>.rotate(n: Int) = 
    let { sliceArray(n until size) + sliceArray(0 until n) }

Example

arrayOf(1, 2, 3, 4, 5).rotate(1)
    .also { println(it.joinToString()) } // 2, 3, 4, 5, 1

Solution 3:[3]

Another extension function, by slicing the array in 2 parts left and right and reassembling it to right + left:

fun <T> Array<T>.leftShift(d: Int) {
    val n = d % this.size  // just in case
    if (n == 0) return  // no need to shift

    val left = this.copyOfRange(0, n)
    val right = this.copyOfRange(n, this.size)
    System.arraycopy(right, 0, this, 0, right.size)
    System.arraycopy(left, 0, this, right.size, left.size)
}

so this:

val a = arrayOf(1, 2, 3, 4, 5, 6, 7)
a.leftShift(2)
a.forEach { print(" " + it) }

will print

3 4 5 6 7 1 2

Solution 4:[4]

Simple solution:

fun <T> Array<T>.rotateLeft(n: Int) = drop(n) + take(n)
fun <T> Array<T>.rotateRight(n: Int) = takeLast(n) + dropLast(n)

The limitation is that n must be less than or equal to the length of the array.

Alternatively, you can use Collections.rotate(...) as follows.

import java.util.Collections

fun <T> Array<T>.rotate(distance: Int) =
    toList().also { // toList() is a deep copy to avoid changing the original array.
        Collections.rotate(it, distance)
    }

fun main() {
    val xs = arrayOf(1, 2, 3, 4, 5)
    val ys = xs.rotate(-2)
    xs.forEach { print("$it ") } // 1 2 3 4 5
    println(ys) // [3, 4, 5, 1, 2]
}

Solution 5:[5]

For the record, you can use the regular Array constructor to build a new array:

inline fun <reified T> Array<T>.rotate(n: Int) = Array(size) { this[(it + n) % size] }

The element at index it in the source array is copied in the destination array at the new index (it + n) % size to perform the rotation.

It is a bit slower than copying the array by chunks.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 awesoon
Solution 2
Solution 3
Solution 4
Solution 5 jferard