如何在72个字符处包装字符串

时间:2018-10-14 11:02:09

标签: swift string

我正在尝试将字符串的文本拆分为不超过72个字符的行(以将行拆分为通常的Usenet引用行长)。划分应该通过用新行替换空格来完成(选择最接近的空格,以便每行<= 72个字符)。 [编辑]

文本以字符串形式出现,并且还可以包含表情符号或其他符号。

我尝试了不同的方法,但是我无法分隔一个单词,但必须在有空格的地方分隔文本这一事实至今仍无法找到解决方法。

有人知道如何在Swift中获得此结果吗?如果需要,还可以使用正则表达式。 [编辑]

1 个答案:

答案 0 :(得分:1)

在其他语言中,您可以使用整数索引字符串。在Swift中不是这样:您必须与它的字符索引进行交互,如果您不熟悉它,可能会感到头痛。

尝试一下:

private func split(line: Substring, byCount n: Int, breakableCharacters: [Character]) -> String {
    var line = String(line)
    var lineStartIndex = line.startIndex

    while line.distance(from: lineStartIndex, to: line.endIndex) > n {
        let maxLineEndIndex = line.index(lineStartIndex, offsetBy: n)

        if breakableCharacters.contains(line[maxLineEndIndex]) {
            // If line terminates at a breakable character, replace that character with a newline
            line.replaceSubrange(maxLineEndIndex...maxLineEndIndex, with: "\n")
            lineStartIndex = line.index(after: maxLineEndIndex)
        } else if let index = line[lineStartIndex..<maxLineEndIndex].lastIndex(where: { breakableCharacters.contains($0) }) {
            // Otherwise, find a breakable character that is between lineStartIndex and maxLineEndIndex
            line.replaceSubrange(index...index, with: "\n")
            lineStartIndex = index
        } else {
            // Finally, forcible break a word
            line.insert("\n", at: maxLineEndIndex)
            lineStartIndex = maxLineEndIndex
        }
    }

    return line
}

func split(string: String, byCount n: Int, breakableCharacters: [Character] = [" "]) -> String {
    precondition(n > 0)
    guard !string.isEmpty && string.count > n else { return string }

    var string = string
    var startIndex = string.startIndex

    repeat {
        // Break a string into lines.
        var endIndex = string[string.index(after: startIndex)...].firstIndex(of: "\n") ?? string.endIndex
        if string.distance(from: startIndex, to: endIndex) > n {
            let wrappedLine = split(line: string[startIndex..<endIndex], byCount: n, breakableCharacters: breakableCharacters)
            string.replaceSubrange(startIndex..<endIndex, with: wrappedLine)
            endIndex = string.index(startIndex, offsetBy: wrappedLine.count)
        }

        startIndex = endIndex
    } while startIndex < string.endIndex
    return string
}

let str1 = "Iragvzvyn vzzntvav chooyvpngr fh Vafgntenz r pv fbab gnagvffvzv nygev unfugnt, qv zvabe fhpprffb, pur nttertnab vzzntvav pba y’vzznapnovyr zntyvrggn"
let str2 = split(string: str1, byCount: 72)
print(str2)

编辑:事实证明,这比我想象的要复杂。通过逐行处理文本,更新后的答案可改善原始答案。您可能会问为什么我设计自己的算法而不是components(separatedBy: "\n")来换行。原因是保留空白行。 components(...)将连续的空白行折叠为一个。