2016-03-28 62 views
6

我想将字符串从“abcde”交换到“bcdea”。所以我写下我的代码如下KotlinKotlin:如何在字符串中交换字符

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] 

它出错了,如上述注释行。我做错了什么?我怎么能解决这个问题,并得到我想要的?

回答

6

Strings in Kotlin就像在Java中是不可变的,所以没有string.set(index, value)(这是string[index] = value等效的东西)。

要构建从碎片字符串你可以使用一个StringBuilder,构建CharSequence和使用joinToString,一个普通的阵列上运行(char[])或做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() 

然而,一个更简单的实现你的目标(“BCDEA”从“ABCDE”)的方式就是“移动”一个字:

var result = prevResult.substring(1) + prevResult[0] 

或使用Sequence方法:

var result = prevResult.drop(1) + prevResult.take(1) 
+0

感谢您的很好的解释! – Elye

+0

考虑使用'buildString'作为构建'String'的更简洁的方法:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/build-string.html – hotkey

0

小号ince字符串是不可变的,您必须将源字符串复制到数组中,对数组进行更改,然后从修改后的数组中创建一个新字符串。看看:

  • getChars()将字符串字符复制到数组中。
  • 在该数组上执行算法,根据需要对其进行更改。
  • 将修改后的数组转换回字符串String(char[])
4

您可以使用drop(1)first()(或take(1))做在同一行:

val str = "abcde" 
val r1 = str.drop(1) + str.first() 
val r2 = str.drop(1) + str.take(1) 

至于你的代码,科特林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) 
} 

let用于简洁,以避免造成更多的变量)


此外,你可以这样写操作的更一般为extension functionString

fun String.rotate(n: Int) = drop(n % length) + take(n % length) 

用法:

val str = "abcde" 
val r1 = str.rotate(1) 
+0

我想知道什么是性能对于那些。在一个天真的实现中,带有'CharArray'的版本必须是最高效的和局部的。另一方面,JIT可以优化其他的,所以有1个分配而不是3个。 – voddan

+1

@voddan,这里是一个测试结果:https://gist.github.com/h0tk3y/bc508a573abfe8e8b3b3。看起来很奇怪,但是drop + take显示它本身更好一点。 – hotkey

+0

哈,没有人期望'StringBuilder'照耀在这里:)谢谢你的测试! – voddan

0

简单的解决办法:只要使用toMutableList()来创建字符的MutableList,然后用joinToString加入它一起。

例子:

给定一个字符串输入,我们要在交换位置POSA和储蓄银行的字符:

val chars = input.toMutableList() 
val temp = chars[posA] 
chars[posA] = chars[posB] 
chars[posB] = temp 
return chars.joinToString(separator = "")