I have an extension here of the String class in Swift that returns the index of the first letter of a given substring.
Can anybody please help me make it so it will return an array of all occurrences instead of just the first one?
Thank you.
extension String {
func indexOf(string : String) -> Int {
var index = -1
if let range = self.range(of : string) {
if !range.isEmpty {
index = distance(from : self.startIndex, to : range.lowerBound)
}
}
return index
}
}
For example instead of a return value of 50
I would like something like [50, 74, 91, 103]
I know we aren't playing code golf here, but for anyone interested in a functional style one-line implementation that doesn't use
var
s or loops, this is another possible solution:There's not really a built-in function to do this, but we can implement a modified Knuth-Morris-Pratt algorithm to get all the indices of the string we want to match. It should also be very performant as we don't need to repeatedly call range on the string.
Here are 2 functions. One returns
[Range<String.Index>]
, the other returns[Range<Int>]
. If you don't need the former, you can make it private. I've designed it to mimic therange(of:options:range:locale:)
method, so it supports all the same features.If you would like just the start indices of each, just tack on
.map{ $0.lowerBound }
You just keep advancing the search range until you can't find any more instances of the substring:
This could be done with recursive method. I used a numeric string to test it. It returns an optional array of
Int
, meaning it will be nil if no substring can be found.