Kotlin:如何在String中交换字符

Ely*_*lye 7 kotlin

我想把一个字符串从"abcde"换成"bcdea".所以我在Kotlin中编写了如下代码

var prevResult = "abcde"
var tmp = prevResult[0]

for (i in 0..prevResult.length - 2) {
    prevResult[i] = prevResult[i+1]  // Error on preveResult[i]
}

prevResult[prevResult.length-1] = tmp // Error on preveResult[prevResult.lengt-1]
Run Code Online (Sandbox Code Playgroud)

如上所述评论行错误.我做错了什么?我怎么能解决这个问题并获得我想要的东西?

szy*_*zym 8

Kotlin中的字符串与Java中的字符串一样是不可变的,因此没有string.set(index, value)(这string[index] = value相当于).

要从片段构建一个字符串,你可以使用a StringBuilder,构造CharSequence和使用joinToString,操作一个普通的数组(char[])或do result = result + nextCharacter(每次创建一个新的字符串 - 这是最昂贵的方式).

这里是你可以用如何做到这一点StringBuilder:

var prevResult = "abcde"
var tmp = prevResult[0]

var builder = StringBuilder()

for (i in 0..prevResult.length - 2) {
  builder.append(prevResult[i+1])
}

builder.append(tmp)  // Don't really need tmp, use prevResult[0] instead.
var result = builder.toString()
Run Code Online (Sandbox Code Playgroud)

然而,一个更简单的方法来实现你的目标("bcdea"来自"abcde")就是"移动"一个角色:

var result = prevResult.substring(1) + prevResult[0]
Run Code Online (Sandbox Code Playgroud)

或使用Sequence方法:

var result = prevResult.drop(1) + prevResult.take(1)
Run Code Online (Sandbox Code Playgroud)


hot*_*key 5

您可以使用drop(1)first()(或take(1))在一行中执行此操作:

val str = "abcde"
val r1 = str.drop(1) + str.first()
val r2 = str.drop(1) + str.take(1)
Run Code Online (Sandbox Code Playgroud)

至于你的代码,Kotlin String是不可变的,你不能修改它的字符.要实现您想要的功能,您可以转换StringCharArray,修改它,然后重新创建String它:

val r1 = str.toCharArray().let {
    for (i in 0..it.lastIndex - 1)
        it[i] = it[i+1]
    it[it.lastIndex] = str[0] // str is unchanged
    String(it)
}
Run Code Online (Sandbox Code Playgroud)

(let用于简明以避免创建更多变量)


此外,你可以写这个操作,作为一个更一般的扩展功能String:

fun String.rotate(n: Int) = drop(n % length) + take(n % length)
Run Code Online (Sandbox Code Playgroud)

用法:

val str = "abcde"
val r1 = str.rotate(1)
Run Code Online (Sandbox Code Playgroud)