Как изменить разные подстроки в строке? - PullRequest
0 голосов
/ 30 января 2019

У меня есть файл с определенным количеством строк.Мне нужно найти все двойные буквы и заменить вторую букву на ту, которая соответствует ей на карте.Регистр замененных букв следует сохранить.Пример:"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.

Ответы [ 4 ]

0 голосов
/ 31 января 2019

Я бы использовал replace , который также принимает лямбда-преобразование, как и горячая клавиша.Но я бы изменил регулярное выражение, чтобы иметь две группы.

  • Первая группа представляет собой позитивный взгляд сзади, что означает, что она будет сопоставлена, но не захвачена, поскольку первую букву не нужно заменять
  • Вторая группа будет захвачена,поскольку вторая буква должна быть заменена другим символом

Код:

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 - это functionol programmyng Longuage

0 голосов
/ 31 января 2019

Попробуйте это.

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, но я думаю, что вы можете немного подправить его, чтобы получить точные результаты.

0 голосов
/ 31 января 2019

Другим идиоматическим решением было бы преобразование согласованной строки с использованием перегрузки replace(...) { ... }, которая принимает лямбду для обработки каждой 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
}

(готовый образец)

0 голосов
/ 30 января 2019

Без каких-либо регулярных выражений:

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 - это функция программирования программ Longuage

...