0

I have a file with a certain number of lines. I need to find all double letters and change the second letter to the one that corresponds to it in the map.
Case of replaced letters should be kept.
Example:
"kotlIn is a functional programming Language"
should become
"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()
}

I spent many hours, but could not find solutions on the Internet and the standard Kotlin library.

4 Answers 4

1

Another idiomatic solution would be to transform the matched string using the 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
}

(runnable sample)

Sign up to request clarification or add additional context in comments.

Comments

1

Without any regex:

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)

will print:

kotlYn is a functionol programmyng Longuage

1 Comment

This is not what i need. I need the value to change only at the letter after klmn. Like in my pattern "([klmn][aei])". And then each aei symbol was replaced with the corresponding one in the map val validChars = mapOf('a' to 'o', 'e' to 'u', 'i' to 'y')
1

Try this.

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}")
}

Prints

NewStr = kotlYn is a functionOl programmYng lOnguage

PS: I'm not that good at Kotlin, but I think you can tweak it a little to get the accurate results.

Comments

1

I would use replace which takes a transform lambda as hotkey proposed as well. But I would change the regex to have two groups.

  • The first group is a positive lookbehind which means that it will be matched but not captured, since the first letter does not have to be replaced
  • The second group will be captured, since the second letter has to be replaced by another character

Code:

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()
    }
}

Result:

kotlYn is a functionol programmyng Longuage

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.