简体   繁体   English

如何在 Kotlin 中使用动态字符串替换?

[英]How to use dynamic string substitution in Kotlin?

I'm looking for a Kotlin way to do a dynamic values substitution into a string.我正在寻找一种 Kotlin 方法来将动态值替换为字符串。 It is clear how to implement it, just want to check if there is something similar in standard library.很清楚如何实现它,只是想检查标准库中是否有类似的东西。

Could you help me to find a function which given template and data map returns a resulting string with all template keys replaced with their values?你能帮我找到一个 function 给定templatedata map 返回一个结果字符串,其中所有模板键都替换为它们的值?

fun format(template: String, data: Map<String, Any>): String { /* magic */ }

format("${a} ${b} ${a}", mapOf("a" to "Home", "b" to "Sweet))   // -> "Home Sweet Home"

Not shorter than lukas.j's answer, just different (using Regex):不比 lukas.j 的答案短,只是不同(使用正则表达式):

val regex = "\\\$\\{([a-z])}".toRegex()

fun format(template: String, data: Map<String, String>) =
    regex.findAll(template).fold(template) { result, matchResult ->
        val (match, key) = matchResult.groupValues
        result.replace(match, data[key] ?: match)
    }

I did not find any thing standard to solve the problem.我没有找到任何标准来解决问题。

So here is a balanced (readability/performance/extensibility) solution also handling cases when some substitutions are undefined in dataMap.因此,这是一个平衡的(可读性/性能/可扩展性)解决方案,它还可以处理 dataMap 中未定义某些替换的情况。

makeString("\${a} # \${b} @ \${c}", mapOf("a" to 123, "c" to "xyz"))   // => "123 # ??? @ xyz"

-- --

object Substitutions {
    private val pattern = Pattern.compile("\\$\\{([^}]+)\\}")

    fun makeString(
        template: String, 
        dataMap: Map<String, Any?>, 
        undefinedStub: String = "???"
    ): String {
        val replacer = createReplacer(dataMap, undefinedStub)
        val messageParts = splitWithDelimiters(template, pattern, replacer)
        return messageParts.joinToString("")
    }

    private fun createReplacer(dataMap: Map<String, Any?>, stub: String): (Matcher) -> String {
        return { m ->
            val key = m.group(1)
            (dataMap[key] ?: stub).toString()
        }
    }

    private fun splitWithDelimiters(
        text: String,
        pattern: Pattern,
        matchTransform: (Matcher) -> String
    ): List<String> {
        var lastMatch = 0
        val items = mutableListOf<String>()
        val m = pattern.matcher(text)

        while (m.find()) {
            items.add(text.substring(lastMatch, m.start()))
            items.add(matchTransform(m))
            lastMatch = m.end()
        }

        items.add(text.substring(lastMatch))

        return items
    }
}
fun format(template: String, data: Map<String, String>): String {
  var retval = template
  data.forEach { dataEntry ->
    retval = retval.replace("\${" + dataEntry.key + "}", dataEntry.value)
  }
  return retval
}

// The $ signs in the template string need to be escaped to prevent
// string interpolation
format("\${a} \${b} \${a}", mapOf("a" to "Home", "b" to "Sweet"))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM