如何在Kotlin中拆分字符串并在拆分的部分之间放置分隔符?

rsl1atfo  于 2023-01-13  发布在  Kotlin
关注(0)|答案(4)|浏览(177)

假设我有一根弦
"Hello! How do you do? Good day!"
我想拆分它,分隔符是:?!,则结果为:

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

但是,我希望它是:

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

ca1c2owp1#

下面是Java中的一个类似问题:How to split a string, but also keep the delimiters?
使用lookahead。在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, !]
3df52oht

3df52oht2#

下面是我对这个函数的理解:

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("!", "?")

不是很快(平方复杂度),但对于相对较短的字符串效果很好。

bybem2ql

bybem2ql3#

下面是一个扩展函数,它封装了here中讨论的代码:

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

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

o75abkj44#

创建具有简单修改的新扩展:

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
}

相关问题