Idiomatic way to replace tokens in a string?

Given the below code - is there any way to make this more idiomatic so that i don’t have to re-assign baseString for every iteration when replacing the token? ideally a single call chain?

fun readAndReplace(): String {
     val tokens = mapOf("{0}" to "WORLD", "{1}" to "KOTLIN")
     var baseString = "HELLO {0}. {1} ROCKS."
     //can you pass baseString into this collection stream?
     tokens.forEach {
         baseString = baseString.replace(it.key, it.value)
     }
     return baseString
 }

Per se this is a fold operation, so you could write it like this:

val result = tokens.entries.fold(baseString)  { 
    string, token -> string.replace(token.key, token.value) 
} 

Now I wouldn’t be sure this is very idiomatic or any clearer than your code, to be honest.
It does avoid a var in the code.

3 Likes

Note that repetitive replacing of tokens doesn’t seem like a best solution performance-wise. If tokens always have a specific format then I guess even regular expressions will be faster:

val regex = Regex("""\{\d+}""") // place it in top-level/singleton
return baseString.replace(regex) { tokens.getOrDefault(it.value, it.value) }

I think that the current code is good as is. It is one of those cases when using a mutable variable is justified and you do not need to make it more complicated.

2 Likes