英文:
Split string by regrex and get matching range
问题
func splitWithRegex(by regexStr: String) -> [(String, Range<String.Index>)] {
guard let regex = try? NSRegularExpression(pattern: regexStr) else { return [] }
let nsRange = NSRange(startIndex..., in: self)
var index = startIndex
var array = regex.matches(in: self, range: nsRange)
.map { match -> (String, Range<String.Index>) in
let range = Range(match.range, in: self)!
let result = self[index..<range.lowerBound]
let substringRange = index..<range.upperBound
index = range.upperBound
return (String(result), substringRange)
}
array.append((String(self[index...]), index..<endIndex))
return array
}
英文:
extension String {
func splitWithRegex(by regexStr: String) -> [String] {
guard let regex = try? NSRegularExpression(pattern: regexStr) else { return [] }
let nsRange = NSRange(startIndex..., in: self)
var index = startIndex
var array = regex.matches(in: self, range: nsRange)
.map { match -> String in
let range = Range(match.range, in: self)!
let result = self[index..<range.lowerBound]
index = range.upperBound
return String(result)
}
array.append(String(self[index...]))
return array
}
}
I use the above code to split a string on Swift using a regrex pattern and return an array of strings
How can I return an object of [(String, Range)]
so I will use the split substrings as keys and it's range as the value.
For example:
let string = "This is a string"
let stringRange = string.splitWithRegex(by: "\\s+")
Result:
(This, 0...4)
(is, 5...7)
(a, 8...9)
(string, 10...16)
答案1
得分: 1
下面是代码的翻译部分:
func splitWithRegex2(by regexStr: String) -> [(String, Range<String.Index>)] {
guard let regex = try? NSRegularExpression(pattern: regexStr) else { return [] }
let nsRange = NSRange(startIndex..., in: self)
var index = startIndex
var array = regex.matches(in: self, range: nsRange)
.compactMap { match -> (String, Range<String.Index>)? in
guard let range = Range(match.range, in: self) else { return nil }
let resultRange = index..<range.lowerBound
let string = String(self[resultRange])
index = range.upperBound
guard !resultRange.isEmpty else { return nil } //This should fix the issue where the first match starts your string, in your case, an empty space
let values = (string, resultRange)
return values
}
//Append last value check: needed?
if index < endIndex {
array.append((String(self[index...]), index..<endIndex))
}
return array
}
要玩:
let stringReg1 = "This is a string"
let stringRange1 = stringReg1.splitWithRegex2(by: "\\s+")
print(stringRange1)
stringRange1.forEach {
let nsRange = NSRange($0.1, in: stringReg1)
print("\($0.0), \(nsRange.location)...\(nsRange.location + nsRange.length)")
}
输出:
[("This", Range(Swift.String.Index(_rawBits: 1)..<Swift.String.Index(_rawBits: 262144))), ("is", Range(Swift.String.Index(_rawBits: 393216)..<Swift.String.Index(_rawBits: 524288))), ("a", Range(Swift.String.Index(_rawBits: 589824)..<Swift.String.Index(_rawBits: 655360))), ("string", Range(Swift.String.Index(_rawBits: 720896)..<Swift.String.Index(_rawBits: 1114113)))]
This, 0...4
is, 6...8
a, 9...10
string, 11...17
let stringReg2 = " This is a string "
let stringRange2 = stringReg2.splitWithRegex2(by: "\\s+")
print(stringRange2)
stringRange2.forEach {
let nsRange = NSRange($0.1, in: stringReg2)
print("\($0.0), \(nsRange.location)...\(nsRange.location + nsRange.length)")
}
输出:
[("This", Range(Swift.String.Index(_rawBits: 262144)..<Swift.String.Index(_rawBits: 524288))), ("is", Range(Swift.String.Index(_rawBits: 655360)..<Swift.String.Index(_rawBits: 786432))), ("a", Range(Swift.String.Index(_rawBits: 851968)..<Swift.String.Index(_rawBits: 917504))), ("string", Range(Swift.String.Index(_rawBits: 983040)..<Swift.String.Index(_rawBits: 1376256)))]
This, 4...8
is, 10...12
a, 13...14
string, 15...21
这是你提供的代码的中文翻译。如果你需要进一步的帮助,请随时告诉我。
英文:
I guess that should do the trick, but I'm not totally sure:
func splitWithRegex2(by regexStr: String) -> [(String, Range<String.Index>)] {
guard let regex = try? NSRegularExpression(pattern: regexStr) else { return [] }
let nsRange = NSRange(startIndex..., in: self)
var index = startIndex
var array = regex.matches(in: self, range: nsRange)
.compactMap { match -> (String, Range<String.Index>)? in
guard let range = Range(match.range, in: self) else { return nil }
let resultRange = index..<range.lowerBound
let string = String(self[resultRange])
index = range.upperBound
guard !resultRange.isEmpty else { return nil } //This should fix the issue where the first match starts your string, in your case, an empty space
let values = (string, resultRange)
return values
}
//Append last value check: needed?
if index < endIndex {
array.append((String(self[index...]), index..<endIndex))
}
return array
}
To play:
let stringReg1 = "This is a string"
let stringRange1 = stringReg1.splitWithRegex2(by: "\\s+")
print(stringRange1)
stringRange1.forEach { //More userfriendly than Range(Swift.String.Index(_rawBits: 65536)..<Swift.String.Index(_rawBits: 327680)))
let nsRange = NSRange($0.1, in: stringReg1)
print("\($0.0), \(nsRange.location)...\(nsRange.location + nsRange.length)")
}
Output:
$>[("This", Range(Swift.String.Index(_rawBits: 1)..<Swift.String.Index(_rawBits: 262144))), ("is", Range(Swift.String.Index(_rawBits: 393216)..<Swift.String.Index(_rawBits: 524288))), ("a", Range(Swift.String.Index(_rawBits: 589824)..<Swift.String.Index(_rawBits: 655360))), ("string", Range(Swift.String.Index(_rawBits: 720896)..<Swift.String.Index(_rawBits: 1114113)))]
$>This, 0...4
$>is, 6...8
$>a, 9...10
$>string, 11...17
let stringReg2 = " This is a string "
let stringRange2 = stringReg2.splitWithRegex2(by: "\\s+")
print(stringRange2)
stringRange2.forEach { //More userfriendly than Range(Swift.String.Index(_rawBits: 65536)..<Swift.String.Index(_rawBits: 327680)))
let nsRange = NSRange($0.1, in: stringReg2)
print("\($0.0), \(nsRange.location)...\(nsRange.location + nsRange.length)")
}
Output:
$>[("This", Range(Swift.String.Index(_rawBits: 262144)..<Swift.String.Index(_rawBits: 524288))), ("is", Range(Swift.String.Index(_rawBits: 655360)..<Swift.String.Index(_rawBits: 786432))), ("a", Range(Swift.String.Index(_rawBits: 851968)..<Swift.String.Index(_rawBits: 917504))), ("string", Range(Swift.String.Index(_rawBits: 983040)..<Swift.String.Index(_rawBits: 1376256)))]
$>This, 4...8
$>is, 10...12
$>a, 13...14
$>string, 15...21
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论