将字符串拆分为包含不大于 n 个字符的字符串的字符串列表

Split string into string list containing strings no greater than n chars

我有一个长字符串,需要将其转换为字符串列表,其中列表中的每个字符串 <= 50 个字符。

此外,我不希望单词被拆分 - 如果第 50 个字符是单词中的一个字母,那么我希望拆分发生在前面的 space。

因此,以下字符串:

什么河流发源于黑森林,流经铁门,流入黑海?

应成为包含以下字符串的字符串列表:

What river rises in the Black Forest, flows 
through the Iron Gate, and empties into the Black 
Sea?

构建链接到的 example @Carsten,这里有一个生成字符串列表的版本,而不是像链接示例那样将它们全部连接在一起:

let until index (text:string) =
    text.[0..index-1]

let from index (text:string) =
    text.[index..]

let wrap fullText lineLength =
    let untilLineLength = until lineLength
    let rec wrapRecursive (text:string) existingLines =
        if text.Length <= lineLength then
            (List.rev ((text.Trim())::existingLines)) //|> String.concat "\n"
        else
            let wrapIndex,nextLineIndex =
                match (text |> untilLineLength).LastIndexOf(" ") with
                | -1 -> lineLength, lineLength
                | spaceIndex -> spaceIndex, spaceIndex + 1
            ((text |> until wrapIndex).Trim())::existingLines |> wrapRecursive (text |> from nextLineIndex) 

    wrapRecursive fullText List.empty

我在递归基本案例中注释掉了 String.concat 以展示如何轻松地将其转换为输出串联字符串。我的示例也应该是尾递归的,这与链接示例不同,它在递归函数中引入了一个累加器列表。

正在测试:

let fullText = "What river rises in the Black Forest, flows through the Iron Gate, and empties into the Black Sea?"

let lineLength = 50

let res = lineLength |> wrap fullText

printfn "%A" res

输出:

["What river rises in the Black Forest, flows"; "through the Iron Gate, and empties into the Black"; "Sea?"]