如何更改字符串中的不同子串?
How to change different substrings in a string?
我有一个包含一定行数的文件。
我需要找到所有双字母并将第二个字母更改为地图中对应的字母。
应保留替换字母的大小写。
示例:
"kotlIn is a functional programming Language"
应变为
"kotlYn is a functionol programmyng Longuage"
fun changeChar(inputFileName: String, outputFileName: String) {
val outputStream = File(outputFileName).bufferedWriter()
val charsRegex = "([klmn][aei])".toRegex(setOf(RegexOption.IGNORE_CASE))
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
File(inputFileName).forEachLine { line ->
val sb = StringBuilder(line).replace(charsRegex, /*here is my difficulty*/)
outputStream.write(sb)
outputStream.newLine()
}
outputStream.close()
}
我花了很多时间,但在互联网和标准 Kotlin 库上找不到解决方案。
没有任何正则表达式:
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
val chars = validChars.plus(validChars.map { it.key.toUpperCase() to it.value.toUpperCase() }.toMap())
var pattern = "klmn"
pattern = pattern.plus(pattern.toUpperCase())
val str = "kotlIn is a functional programming Language"
val result = str.mapIndexed { i, c ->
if (i > 0) { if (pattern.contains(str[i -1])) chars.getOrDefault(c, c) else c } else c
}.joinToString("")
println(result)
将打印:
kotlYn is a functionol programmyng Longuage
试试这个。
fun main(args: Array<String>) {
val str = "kotlIn is a functional programming Language"
val validChars = mapOf("a" to "o", "e" to "u", "i" to "y" )
val charsRegex = "(?=(.))([klmn][aei])(?<=(.))".toRegex(setOf(RegexOption.IGNORE_CASE))
val found = charsRegex.findAll(str)
var newStr= str
found.forEach { f ->
val m = f.value.toLowerCase()
val idx = f.range
val k = m.substring(1)
val repStr = m.substring(0,1) + validChars.get(k)?.toUpperCase()
newStr= newStr.replaceRange(idx,repStr)
// println("$m found at indexes: $idx ${validChars.get(k)} ${newStr}" )
}
println( "NewStr = ${newStr}")
}
版画
NewStr = kotlYn is a functionOl programmYng lOnguage
PS:我不太擅长 Kotlin,但我认为您可以稍微调整一下以获得准确的结果。
另一个惯用的解决方案是使用 replace(...) { ... }
overload that accepts a lambda to handle each MatchResult
:
转换匹配的字符串
val charsRegex = "[klmn][aei]".toRegex(RegexOption.IGNORE_CASE)
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
val result = line.replace(charsRegex) {
val vowel = it.value[1]
val validLetter = validChars.getValue(vowel.toLowerCase())
val validCaseLetter = if (vowel.isLowerCase()) validLetter else validLetter.toUpperCase()
it.value.take(1) + validCaseLetter
}
我会使用 replace,它也采用转换 lambda 作为热键。但我会将正则表达式更改为有两组。
- 第一组是正后向,这意味着它会被匹配但不会被捕获,因为不必替换第一个字母
- 第二组将被捕获,因为第二个字母必须由另一个字符替换
代码:
fun replaceInvalidPairs(line: String): String {
val charsRegex = "(?<=[klmn])([aei])".toRegex(setOf(RegexOption.IGNORE_CASE))
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
return charsRegex.replace(line) {
val secondLetter = it.groupValues.first().first()
val replacement = validChars[secondLetter.toLowerCase()]!!
(if (secondLetter.isUpperCase()) replacement.toUpperCase() else replacement).toString()
}
}
结果:
kotlYn is a functionol programmyng Longuage
我有一个包含一定行数的文件。
我需要找到所有双字母并将第二个字母更改为地图中对应的字母。
应保留替换字母的大小写。
示例:"kotlIn is a functional programming Language"
应变为 "kotlYn is a functionol programmyng Longuage"
fun changeChar(inputFileName: String, outputFileName: String) {
val outputStream = File(outputFileName).bufferedWriter()
val charsRegex = "([klmn][aei])".toRegex(setOf(RegexOption.IGNORE_CASE))
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
File(inputFileName).forEachLine { line ->
val sb = StringBuilder(line).replace(charsRegex, /*here is my difficulty*/)
outputStream.write(sb)
outputStream.newLine()
}
outputStream.close()
}
我花了很多时间,但在互联网和标准 Kotlin 库上找不到解决方案。
没有任何正则表达式:
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
val chars = validChars.plus(validChars.map { it.key.toUpperCase() to it.value.toUpperCase() }.toMap())
var pattern = "klmn"
pattern = pattern.plus(pattern.toUpperCase())
val str = "kotlIn is a functional programming Language"
val result = str.mapIndexed { i, c ->
if (i > 0) { if (pattern.contains(str[i -1])) chars.getOrDefault(c, c) else c } else c
}.joinToString("")
println(result)
将打印:
kotlYn is a functionol programmyng Longuage
试试这个。
fun main(args: Array<String>) {
val str = "kotlIn is a functional programming Language"
val validChars = mapOf("a" to "o", "e" to "u", "i" to "y" )
val charsRegex = "(?=(.))([klmn][aei])(?<=(.))".toRegex(setOf(RegexOption.IGNORE_CASE))
val found = charsRegex.findAll(str)
var newStr= str
found.forEach { f ->
val m = f.value.toLowerCase()
val idx = f.range
val k = m.substring(1)
val repStr = m.substring(0,1) + validChars.get(k)?.toUpperCase()
newStr= newStr.replaceRange(idx,repStr)
// println("$m found at indexes: $idx ${validChars.get(k)} ${newStr}" )
}
println( "NewStr = ${newStr}")
}
版画
NewStr = kotlYn is a functionOl programmYng lOnguage
PS:我不太擅长 Kotlin,但我认为您可以稍微调整一下以获得准确的结果。
另一个惯用的解决方案是使用 replace(...) { ... }
overload that accepts a lambda to handle each MatchResult
:
val charsRegex = "[klmn][aei]".toRegex(RegexOption.IGNORE_CASE)
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
val result = line.replace(charsRegex) {
val vowel = it.value[1]
val validLetter = validChars.getValue(vowel.toLowerCase())
val validCaseLetter = if (vowel.isLowerCase()) validLetter else validLetter.toUpperCase()
it.value.take(1) + validCaseLetter
}
我会使用 replace,它也采用转换 lambda 作为热键。但我会将正则表达式更改为有两组。
- 第一组是正后向,这意味着它会被匹配但不会被捕获,因为不必替换第一个字母
- 第二组将被捕获,因为第二个字母必须由另一个字符替换
代码:
fun replaceInvalidPairs(line: String): String {
val charsRegex = "(?<=[klmn])([aei])".toRegex(setOf(RegexOption.IGNORE_CASE))
val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
return charsRegex.replace(line) {
val secondLetter = it.groupValues.first().first()
val replacement = validChars[secondLetter.toLowerCase()]!!
(if (secondLetter.isUpperCase()) replacement.toUpperCase() else replacement).toString()
}
}
结果:
kotlYn is a functionol programmyng Longuage