【问题标题】:Modify the content of a large string修改大字符串的内容
【发布时间】:2021-07-29 06:00:26
【问题描述】:

我收到了一些包含多个数字划分部分的大型字符串内容。
我试图以这样的方式修改内容,如果存在数字,则插入换行符。

就像这样:“1.这是一行。2.这是另一行。3.这是另外一个。”

被修改成这样的:
“1.这是一行。
2. 这是另一行。
3. 这是另外一行。”

我试过这样解决:

fun modifyText(inputStr: String):String {
        val marker= listOf('1', '2', '3', '4', '5', '6', '7')
        var text = ""
       marker.forEach {
           if (inputStr.contains(it)) {
               text = inputStr.replace(it.toString(), "\n $it" )
           }
       }
       return text
}

这仅修改了最后一个数字的部分,而不是所有内容。 以这种方式使用递归的想法:

tailrec fun modifyText(inputStr: String):String {
        val marker= listOf('1', '2', '3', '4', '5', '6', '7')
        var text = ""
       marker.forEach {
           if (inputStr.contains(it)) {
               text = inputStr.replace(it.toString(), "\n $it" )
           }
       }
       return modifyText(text)
} 
but ended up "bricking" the app.
Please any solutions to how this can be achieved will be appreciated.

【问题讨论】:

    标签: android string kotlin recursion


    【解决方案1】:

    您的第二次尝试“破坏了应用程序”,因为您正在编写一个具有无限递归的函数(它调用自身但没有停止条件)。这通常会因StackOverflowError 而失败,但对于tailrec,您可能会以无限循环结束——也好不到哪里去。

    在您的情况下不需要递归,replace() 将处理所有匹配字符串的出现。

    您第一次尝试的问题是text = inputStr.replace(it.toString(), "\n $it" ) 总是重用初始的inputStr 而不是修改后的text。因此,您已经进行的所有替换都不会被考虑在内,只有最后一个“标记”(7)的替换才有效。 您可以通过使用text 而不是inputStr 来更改它,并将text 初始化为inputStr

    fun modifyText(inputStr: String):String {
        val marker= listOf('1', '2', '3', '4', '5', '6', '7')
        var text = inputStr
        marker.forEach {
            if (inputStr.contains(it)) {
                text = text.replace(it.toString(), "\n $it" )
            }
        }
        return text
    } 
    

    请注意,为此您也可以直接使用正则表达式,而无需手动列出所有数字。它可能更高效,更重要的是它更简单:

    val modifiedStr = inputStr.replace(Regex("""\d"""), "\n $0")
    

    如果您不熟悉正则表达式,会发生以下情况:

    • \d 匹配单个数字
    • 替换字符串中的$0 表示匹配组 0 的值,即整个匹配项(因此,正则表达式匹配的数字)。如果正则表达式中有括号,则每对括号定义一个新组(编号为 1、2、3 等)。

    如果你想匹配数字后跟.,你也可以改进这个正则表达式(在你的输入中,它看起来总是跟着.,所以它会避免匹配不是节号的数字):

    val modifiedStr = inputStr.replace(Regex("""\d\."""), "\n $0")
    

    最后一项改进,如果您有超过 1 位的部分编号,您可以使用 + 修饰符来表示“一个或多个”:

    val modifiedStr = inputStr.replace(Regex("""\d+\."""), "\n $0")
    

    【讨论】:

    • 这比我尝试的正则表达式解决方案更整洁。它也可以匹配“\d+\”。如果需要期间。
    • @PPartisan 我正在编辑以添加这个:)
    【解决方案2】:

    您可以用标记+换行符替换字符串中的每个“标记”字符。 不需要递归。 像这样的

    val marker= listOf('1', '2', '3', '4', '5', '6', '7')
    var text = inputStr
    marker.forEach {
       text = text.replace(it.toString(), "\n$it" )
    }
    return text
    

    【讨论】:

    • 由于列表中存在“1”,您不会在开头有一个新行吗?
    【解决方案3】:

    您的所有逻辑都很好,但是您缺少一些东西。您必须使用更新值更新旧字符串。

          fun main() {
                    var inputStr = "1. This is one line. 2. This is another. 3. 
                     Here is one more."
                     val marker= listOf('1', '2', '3', '4', 
                     '5', '6', '7')
                       var text = ""
                      marker.forEach {
                        if (inputStr.contains(it)) {
                  text = inputStr.replace(it.toString(), "\n $it" )
                **// so only add this , and it will work fine :)**
                 inputStr=text
             }
                  println(text)
         }
        
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-10
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2020-12-08
      • 1970-01-01
      相关资源
      最近更新 更多