在Swift中将字符串拆分为数组并保留分隔符/分割符

4
寻找一种(优雅的)解决方案,可以将字符串拆分并将分隔符保留为数组项。
示例1:
"hello world"

["hello", " ", "world"]

例子2:

" hello world"

[" ", "hello", " ", "world"]

谢谢。


1
这个 https://dev59.com/iY7ea4cB1Zd3GeqPE7h6 怎么样? - Martin R
@MartinR 谢谢链接。我搜索了解决方案,但没有找到这个。那个问题的解决方案很有启发性,但对于分隔符长度超过一个字符的情况不起作用。第二个例子似乎也不起作用。 - fetzig
4个回答

10

假设您要按名为 separator 的分隔符拆分字符串,可以执行以下操作:

let result = yourString.components(separatedBy:  separator) // first split
                        .flatMap { [$0, separator] } // add the separator after each split
                        .dropLast() // remove the last separator added
                        .filter { $0 != "" } // remove empty strings

例如:

let result = " Hello World ".components(separatedBy:  " ").flatMap { [$0, " "] }.dropLast().filter { $0 != "" }
print(result) // [" ", "Hello", " ", "World", " "]

@Sweeper 我记得有一个版本的 components(separatedBy:) 有一个可选参数可以排除空结果。你见过类似的东西吗? - Alexander
我知道你可以在C#中做到这一点,但我不认为Swift中存在这样的功能。@Alexander - Sweeper

1

对于需要根据大写字母条件拆分camelCase字符串的人:

extension Sequence {
    func splitIncludeDelimiter(whereSeparator shouldDelimit: (Element) throws -> Bool) rethrows -> [[Element]] {
        try self.reduce([[]]) { group, next in
            var group = group
            if try shouldDelimit(next) {
                group.append([next])
            } else {
                group[group.lastIdx].append(next)
            }
            return group
        }
    }
}

例如:

"iAmCamelCase".splitIncludeDelimiter(whereSeparator: \.isUppercase)
=>
["i", "Am", "Camel", "Case"]

(如果你想要isUppercase的重要性)

extension CharacterSet {
    static let uppercaseLetters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
}

extension Unicode.Scalar {
    var isUppercase: Bool {
        CharacterSet.uppercaseLetters.contains(self)
    }
}

0

仅仅是为了好玩,Swift Algorithms 包含一个名为 Intersperse 的算法。

在添加了该包之后,

import Algorithms

你可以写

let string = "hello world"
let separator = " "

let result = Array(string
                     .components(separatedBy: separator)
                     .interspersed(with: separator))
print(result)

你的第二个例子几乎是正确的,将" hello world"按空格分割的结果是

["", "hello", "world"]

0
let sample = "a\nb\n\nc\n\n\nd\n\nddddd\n \n  \n  \n\n"

let sep = "\n"

let result = sample.components(separatedBy: sep).flatMap {
    $0 == "" ? [sep] : [$0, sep]
}.dropLast()


debugPrint(result) // ArraySlice(["a", "\n", "b", "\n", "\n", "c", "\n", "\n", "\n", "d", "\n", "\n", "ddddd", "\n", " ", "\n", "  ", "\n", "  ", "\n", "\n"])


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