移位Kotlin数组

时间:2018-10-19 11:43:13

标签: kotlin

假设我有一个像1 2 3 4 5这样的数组,我想将其向左旋转 n 并得到一个新的数组。

例如,上述数组的2旋转将导致3 4 5 1 2。我没有找到任何扩展功能来做到这一点。

6 个答案:

答案 0 :(得分:4)

您可以使用内置的Java Collections.rotate方法,但是需要首先将数组转换为列表:

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

输出

3, 4, 5, 1, 2

答案 1 :(得分:3)

简单的解决方案:

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

限制是 n 必须小于或等于数组的长度。

或者,您可以按如下方式使用 Collections.rotate(...)

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

答案 2 :(得分:2)

您可以在Array<T>上编写自己的扩展功能

fun <T> Array<T>.leftShift(d: Int): Array<T> {
    val newList = this.copyOf()
    var shift = d
    if (shift > size) shift %= size
    forEachIndexed { index, value ->
        val newIndex = (index + (size - shift)) % size
        newList[newIndex] = value
    }
    return newList
}

答案 3 :(得分:2)

另一个扩展功能,通过将数组切成两部分leftright并将其重组为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)
}

所以这个:

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

将打印

3 4 5 6 7 1 2

答案 4 :(得分:2)

我解释“获得一个新的” 意味着扩展功能应该返回一个新的实例,就像这样(省略边界检查):

x.insert(0, a);

答案 5 :(得分:0)

作为记录,您可以使用常规的Array constructor来构建一个新数组:

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

将源数组中索引为it的元素复制到目标数组中新索引为(it + n) % size的位置以进行旋转。

这比分块复制数组要慢一些。