【问题标题】:How to get components separated by regular expression, but also with separators?如何让组件用正则表达式分隔,也用分隔符?
【发布时间】:2019-07-26 08:20:14
【问题描述】:

我有一个字符串扩展名:

extension String {
    func split(usingRegex pattern: String) -> [String] {
        let regex = try! NSRegularExpression(pattern: pattern)
        let matches = regex.matches(in: self, range: NSRange(0..<utf16.count))
        let ranges = [startIndex..<startIndex] + matches.map{Range($0.range, in: self)!} + [endIndex..<endIndex]
        return (0...matches.count).map {String(self[ranges[$0].upperBound..<ranges[$0+1].lowerBound])}
    }
}

我是这样使用它的:

var string = "Hello45playground23today"
var output = string.split(usingRegex: "[0-9]+")

输出是:

["Hello", "playground", "today"]

但我需要的是:

["Hello", "45", "playground", "23", "today"]

有没有办法在 Swift 中实现这一点?

【问题讨论】:

  • 可以选择正则表达式吗?

标签: ios swift string


【解决方案1】:

您的代码仅将匹配项之间的子字符串(以及第一个匹配项之前和最后一个匹配项之后)添加到结果中。您还需要匹配项本身的子字符串。这可以通过创建一个包含匹配开始或结束的所有索引的数组来完成,然后在连续索引之间获取所有子字符串:

extension String {
    func split(usingRegex pattern: String) -> [String] {
        let regex = try! NSRegularExpression(pattern: pattern)
        let matches = regex.matches(in: self, range: NSRange(startIndex..., in: self))
        let splits = [startIndex]
            + matches
                .map { Range($0.range, in: self)! }
                .flatMap { [ $0.lowerBound, $0.upperBound ] }
            + [endIndex]

        return zip(splits, splits.dropFirst())
            .map { String(self[$0 ..< $1])}
    }
}

例子:

let string = "Hello45playground23today"
let output = string.split(usingRegex: "[0-9]+")
print(output) // ["Hello", "45", "playground", "23", "today"]

显式循环也可以做到这一点(不太复杂,但可读性更好):

extension String {
    func split(usingRegex pattern: String) -> [String] {
        let regex = try! NSRegularExpression(pattern: pattern)
        let matches = regex.matches(in: self, range: NSRange(startIndex..., in: self))
        var result: [String] = []
        var pos = startIndex
        for match in matches {
            let range = Range(match.range, in: self)!
            result.append(String(self[pos..<range.lowerBound]))
            result.append(String(self[range]))
            pos = range.upperBound
        }
        result.append(String(self[pos...]))
        return result
    }
}

【讨论】:

  • 很好的答案。 @BartłomiejSemańczyk 为了好玩,您还可以使用简单的正则表达式但仅用于具有相同长度数字的字符串:(?&lt;=\d{2})|(?=\d{2})
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多