How about this:
extension String {
func multiSplit(inds: [String.Index]) -> [String] {
if let loc = inds.last {
return self[self.startIndex..<loc].multiSplit(Array(dropLast(inds))) + [self[loc..<self.endIndex]]
} else {
return [self]
}
}
}
let string = "abcdef"
let inds = [
string.startIndex.successor().successor(),
string.endIndex.predecessor().predecessor()
]
string.multiSplit(inds) // ["ab", "cd", "ef"]
The indices you give it have to be in order to work.
It's a recursive function - it takes the last index in the array of indices it's given (inds), and splits the string at that index. The first half of that split is recursively given to itself, with the last element of the array of indices removed. The "if let" fails if the index array is empty, so it just returns the string without any splits, but in an array of one.
In the example, It'll first split at the last index it's given, and get two strings: "abcd" and "ef". Then, the function calls itself with "abcd", and an array of indices without the last element (dropLast()). In this function, it'll split "abcd" into "ab" and "cd", and call itself again on "ab". But, since it passes an empty array to that function, the inds.last will fail, and it won't split anything, and just return ["ab"] (the line with return [self]). This goes up to the function above - which appends its split ("cd") onto it, and returns ["ab", "cd"]. This, finally, goes to the function above, which appends its split, and it returns the answer: ["ab, "cd", "ef"].
It's all just normal Swift, though, no imports or anything.
If you were dealing with indices out of order, you can just sort them:
let string = "abcdef"
let inds = [
string.endIndex.predecessor().predecessor(),
string.startIndex.successor().successor()
]
string.multiSplit(sorted(inds)) // ["ab", "cd", "ef"]
Also, if you want to remove empty strings from within the function:
extension String {
func multiSplit(inds: [String.Index]) -> [String] {
if let loc = inds.last {
return (
self[self.startIndex..<loc]
.multiSplit(Array(dropLast(inds)))
+ [self[loc..<self.endIndex]]
).filter{!$0.isEmpty}
} else {
return [self]
}
}
}
componentsSeperatedByString:for each of my tokens, which builds a tree-like structure, and then simply flatten the tree. This may not be optimal, but it'd work.