我有一个字符串"323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography"
我想使用正则表达式[0-9][0-9][0-9][A-Z][A-Z][A-Z]
拆分此字符串,以便该函数返回数组:
Array =
["323 ECO Economics Course ", "451 ENG English Course", "789 Mathematical Topography"]
我如何使用swift进行此操作?
修改
我的问题与链接的问题不同。我意识到您可以使用myString.components(separatedBy: "splitting string")
在swift中拆分字符串。问题是该问题没有解决如何使splitting string
成为正则表达式的问题。我尝试使用mystring.components(separatedBy: "[0-9][0-9][0-9][A-Z][A-Z][A-Z]", options: .regularExpression)
,但这不起作用。
如何使separatedBy:
部分成为正则表达式?
答案 0 :(得分:4)
您可以使用正则表达式"\\b[0-9]{1,}[a-zA-Z ]{1,}"
和此answer中的此扩展名来使用literal,caseInsensitive或regularExpression搜索获取字符串的所有范围:
extension String {
func ranges(of string: String, options: CompareOptions = .literal) -> [Range<Index>] {
var result: [Range<Index>] = []
var start = startIndex
while let range = range(of: string, options: options, range: start..<endIndex) {
result.append(range)
start = range.lowerBound < range.upperBound ? range.upperBound : index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
}
return result
}
}
let inputString = "323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography"
let courses = inputString.ranges(of: "\\b[0-9]{1,}[a-zA-Z ]{1,}", options: .regularExpression).map{inputString[$0] }
print(courses) // ["323 ECO Economics Course ", "451 ENG English Course ", "789 Mathematical Topography"]
答案 1 :(得分:2)
Swift目前还没有原生正则表达式。但Foundation
提供了NSRegularExpression
。
import Foundation
let toSearch = "323 ECO Economics Course 451 ENG English Course 789 MAT Mathematical Topography"
let pattern = "[0-9]{3} [A-Z]{3}"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
// NSRegularExpression works with objective-c NSString, which are utf16 encoded
let matches = regex.matches(in: toSearch, range: NSMakeRange(0, toSearch.utf16.count))
// the combination of zip, dropFirst and map to optional here is a trick
// to be able to map on [(result1, result2), (result2, result3), (result3, nil)]
let results = zip(matches, matches.dropFirst().map { Optional.some($0) } + [nil]).map { current, next -> String in
let range = current.rangeAt(0)
let start = String.UTF16Index(range.location)
// if there's a next, use it's starting location as the ending of our match
// otherwise, go to the end of the searched string
let end = next.map { $0.rangeAt(0) }.map { String.UTF16Index($0.location) } ?? String.UTF16Index(toSearch.utf16.count)
return String(toSearch.utf16[start..<end])!
}
dump(results)
运行它将输出
▿ 3 elements
- "323 ECO Economics Course "
- "451 ENG English Course "
- "789 MAT Mathematical Topography"
答案 2 :(得分:0)
我需要这样的东西,应该更像 JS String.prototype.split(pat: RegExp) 或 Rust 的 String.splitn(pat: Pattern<'a>) 但使用 Regex。我结束了这个
extension NSRegularExpression {
convenience init(_ pattern: String) {...}
/// An array of substring of the given string, separated by this regular expression, restricted to returning at most n items.
/// If n substrings are returned, the last substring (the nth substring) will contain the remainder of the string.
/// - Parameter str: String to be matched
/// - Parameter n: If `n` is specified and n != -1, it will be split into n elements else split into all occurences of this pattern
func splitn(_ str: String, _ n: Int = -1) -> [String] {
let range = NSRange(location: 0, length: str.utf8.count)
let matches = self.matches(in: str, range: range);
var result = [String]()
if n != -1 && n < 2 { return [str] }
if let first = matches.first?.range {
if first.location == 0 { result.append("") }
if first.location != 0 {
let _range = NSRange(location: 0, length: first.location)
result.append(String(str[Range(_range, in: str)!]))
}
}
for (cur, next) in zip(matches, matches[1...]) {
let loc = cur.range.location + cur.range.length
if n != -1 && result.count + 1 == n {
let _range = NSRange(location: loc, length: str.utf8.count - loc)
result.append(String(str[Range(_range, in: str)!]))
return result
}
let len = next.range.location - loc
let _range = NSRange(location: loc, length: len)
result.append(String(str[Range(_range, in: str)!]))
}
if let last = matches.last?.range, !(n != -1 && result.count >= n) {
let lastIndex = last.length + last.location
if lastIndex == str.utf8.count { result.append("") }
if lastIndex < str.utf8.count {
let _range = NSRange(location: lastIndex, length: str.utf8.count - lastIndex)
result.append(String(str[Range(_range, in: str)!]))
}
}
return result;
}
}
通过以下测试
func testRegexSplit() {
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn("My . Love"), ["My", "Love"])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn("My . Love . "), ["My", "Love", ""])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn(" . My . Love"), ["", "My", "Love"])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn(" . My . Love . "), ["", "My", "Love", ""])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX"), ["", "My", "", "Love", ""])
}
func testRegexSplitWithN() {
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 1), ["xXMyxXxXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", -1), ["", "My", "", "Love", ""])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 2), ["", "MyxXxXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 3), ["", "My", "xXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 4), ["", "My", "", "LovexX"])
}