doublemc
doublemc

Reputation: 3301

Replace fractions to decimals in string

I need to replace fraction in given string to decimal. So:

1/4 xx -> 0.25 xx
1/3 xx -> 0.33 xx

Above exampels I got covered with:

private fun String.replaceFractions() = "(?:[1-9]*)/[1-9]*".toRegex().find(this)
        ?.let {
            val fraction = it.groups[0]!!.value
            val fractionParts = fraction.split("/")
                    .map { part -> part.toDouble() }
            this.replace(fraction, (fractionParts[0] / fractionParts[1]).toString())
        }
        ?: this

But I cannot find a way to replace properly string when they also have whole part:

1 1/4 xx -> 1.25 xx
3 3/5 xx -> 3.6 xx

Upvotes: 1

Views: 217

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626758

You may achieve what you want with a mere replace like

val s = "Some text: 1/4 and 3 3/5"
val result = s.replace("""(?:(\d+(?:\.\d+)?)\s+)?(\d+)/(\d+)""".toRegex()) {
    ((if (it.groupValues[1].isNullOrEmpty()) 0.0 else it.groupValues[1].toDouble()) + (it.groupValues[2].toDouble() / it.groupValues[3].toDouble())).toString()
}    
println(result) // => Some text: 0.25 and 3.6

See Kotlin demo

Regex details

  • (?:(\d+(?:\.\d+)?)\s+)? - an optional non-capturing group matching 1 or 0 occurrences of:
    • (\d+(?:\.\d+)?) - Group 1: 1+ digits, and then 1 or 0 (optional) sequence of . and 1+ digits
    • \s+ - 1+ whitespaces
    • (\d+) - Group 2: 1+ digits
  • / - a / char
  • (\d+) - Group 3: 1+ digits

If Group 1 matched, its value is cast to double, else, 0 is taken, and the value is summed with the result of Group 2 and Group 3 division.

Upvotes: 1

Related Questions