如何在 Kotlin 中拆分字符串并将分隔符插入已拆分的部分之间?

9

假设我有一个字符串:

"Hello! How do you do? Good day!"

我想用分隔符?!来进行切割,使用 "split" 函数的话结果应该是:

`[Hello, How do you do, Good day]`

然而,我希望它是这样的:
`[Hello, !, How do you do, ?, Good day, !]`
4个回答

13

这里有一个类似的Java问题:如何拆分一个字符串,同时保留分隔符?

使用前瞻。在Kotlin中,代码可能是这样的:

fun main(args: Array<String>) {
    val str = "Hello! How do you do? Good day!"

    val reg = Regex("(?<=[!?])|(?=[!?])")

    var list = str.split(reg)

    println(list)
}

它的输出结果是:

[Hello, !, How do you do, ?, Good day, !]

1
这个解决方案似乎会在字符串以分割模式开头或结尾时创建空列表条目。此外,它似乎无法使用类似于\d+的分割模式来匹配多个数字。 - sschuberth

2

这是我实现的该函数版本:

fun String.splitKeeping(str: String): List<String> {
    return this.split(str).flatMap {listOf(it, str)}.dropLast(1).filterNot {it.isEmpty()}
}

fun String.splitKeeping(vararg strs: String): List<String> {
    var res = listOf(this)
    strs.forEach {str -> 
        res = res.flatMap {it.splitKeeping(str)}
    }
    return res
}

//USAGE:
"Hello! How do you do? Good day!".splitKeeping("!", "?")

虽然它的复杂度是平方级别,但对于相对较短的字符串效果很好。


1
你有没有可能编写一个函数,用于正则表达式分隔符? - Dina Kleper
@user3601872 这是我过去一个项目中的一段代码。如果您能够改进它,请随意在这里发布,这样我也可以从中受益。 - voddan

1

这里是一个扩展函数,包装了这里讨论的代码:

private const val withDelimiter = "((?<=%1\$s)|(?=%1\$s))"

fun Regex.splitWithDelimiter(input: CharSequence) = 
    Regex(withDelimiter.format(this.pattern)).split(input)

0
创建一个新的扩展,其中包含一个简单的修改:
private fun CharSequence.splitWithDelimiters(delimiter: String, ignoreCase: Boolean = false, limit: Int = 0): List<String> {
    require(limit >= 0) { "Limit must be non-negative, but was $limit" }

    var currentOffset = 0
    var nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
    if (nextIndex == -1 || limit == 1) {
        return listOf(this.toString())
    }

    val isLimited = limit > 0
    val result = ArrayList<String>(if (isLimited) limit.coerceAtMost(10) else 10)
    do {
        result.add(substring(currentOffset, nextIndex))
        // Adding delimiter(s) 
        result.add(substring(nextIndex, nextIndex + delimiter.length))
        currentOffset = nextIndex + delimiter.length
        // Do not search for next occurrence if we're reaching limit
        if (isLimited && result.size == limit - 1) break
        nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
    } while (nextIndex != -1)

    result.add(substring(currentOffset, length))
    return result
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接