我试图将Swift脚本移植到Kotlin但是它没有按预期工作,代码的作用是在条件为真时使用字符串(需要它用于解析器)。在Swift中,它按预期工作,但在Kotlin中却没有(我一个月前刚开始使用Kotlin,所以也许我错过了一些东西)。
夫特
extension String {
@discardableResult public mutating func consumeWhile(test: (String) -> Bool) -> String {
var chars = [Character](self.characters)
var result = ""
while chars.count > 0 && test(String(chars[0])) {
result.append(chars.remove(at: 0))
}
self = String(chars)
return result
}
}
科特林
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
var result = ""
var i = -1
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
++i
}
removeRange(0..i)
return result
}
所以基本用法看起来像
val myString = "--Test" // IntelliJ suggests change var to val
val consumedString = myString.consumeWhile{ it != "-" }
println("result: $myString consumedString: $consumedString")
// expected: "result: Test consumedString: --"
// but got: "result: --Test consumedString: --"
编辑:感谢所有答案,不知道是否可以像我想的那样做,因为提到的字符串在Kotlin / Java中是不可变的(只是使用相同的字符串)。 / p>
我忘了提到我需要消耗的字符串,基本上是b / c我正在做一个解析器所以我需要存储消耗的字符和变异的字符串。我将打开这个问题,但我最终创建了一个只实现几个String类方法的类。
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
使用示例
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
答案 0 :(得分:0)
在Java和Kotlin String
中都是不可变的,在创建它之后就无法更改它。
在swift中,这可能是通过mutating
修饰符关闭的。但是在Kotlin中removeRange(0..i)
会创建一个新的String对象,然后将其丢弃。
要让它按照您的意愿行事,您需要:
Pair
返回,然后您可以使用解构运算符将其指定为[_, myString] = myString.consumeWhile {}
答案 1 :(得分:0)
Kotlin字符串是不可变的,无法在适当的位置进行修改。相反,您可以创建一个新的String并将其返回
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
while (chars.isNotEmpty() && test(chars.first().toString())) {
chars.removeAt(0)
// Do something with the char
}
return chars.joinToString(separator = "")
}
此外,除非我误解,否则您的测试条件应为it == "-"
以获得您想要的结果:
val myString = "--Test"
val newString = myString.consumeWhile{ it == "-" }
println("result: $newString")
答案 2 :(得分:0)
字符串在Kotlin&中是不可变的。 Java,所以无论如何你都无法修改它的状态。
你应该避免重复制作轮子,Kotlin中有一个现有的函数String#dropWhile(Char)。您需要做的一件事是反转条件,例如:
val result = "--Test".dropWhile { it == '-' }
// ^--- "Test"
答案 3 :(得分:0)
您使用
myString.consumeWhile{ it != "-" }
一旦遇到第一个" - "就会停止消费,因此无需再做任何事情。
如果使用
,代码可以正常工作myString.consumeWhile{ it == "-" }
您将获得正确的预期输出。
答案 4 :(得分:0)
我最终创建了一个只实现几个String类方法的类。
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
使用示例
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
Obs:现在将标记为已回答,直到找到更好的解决方案