How can we subtract multiple ranges of type Range<String.Index> from one range of type Range<String.Index>?
Example:
let str = "let <#name#> = <#value#>"
let range = str.startIndex..<str.endIndex
//the range of str is {0, 24}
//the range of <#name#> is {4, 8}
//the range of <#value#> is {15, 9}
How can we subtract the ranges {4, 8} and {15, 9} from the range of str to obtain the ranges of "let " and " = "
Here's an extension to StringProtocol
that will return an array of ranges from a string that are outside the passed in ranges:
extension StringProtocol {
func ranges(outsideOf ranges: [Range<String.Index>]) -> [Range<String.Index>] {
var res = [Range<String.Index>]()
var lastEnd = self.startIndex
// Iterate each provided range (sorted by lowerBound)
for range in ranges.sorted(by: { $0.lowerBound < $1.lowerBound }) {
// Added the result if this range has space before the previous range
if range.lowerBound > lastEnd {
res.append(Range(uncheckedBounds: (lastEnd, range.lowerBound)))
}
if range.upperBound > lastEnd {
lastEnd = range.upperBound
}
}
// If there's any space after the last range, add that to the result
if lastEnd < self.endIndex {
res.append(Range(uncheckedBounds: (lastEnd, self.endIndex)))
}
return res
}
}
Here's some sample code to demonstrate its use:
let str = "let <@name@> = <@value@>"
let nameRng = str.range(of: "<@name@>")!
let valueRng = str.range(of: "<@value@>")!
let ranges = str.ranges(outsideOf: [nameRng, valueRng])
print(ranges.map { str[$0] })
Output:
["let ", " = "]