General remarks
value
, as a parameter name, isn't very descriptive,
The code considers that white spaces can only be " "
or "\n"
or "\t"
. This a performance optimization and supposes prior knowledge of the contents of the string. More generally you could make the check this way:
if char.isWhitespace {
indices.append(index)
}
Array<Int>
is not the same as [String.Index]
of IndexSet. A String
can be traversed using String.Index
and not and Int
.
Performance
The following codeis twice as fast in my tests, but doesn’t work with emoji :
func whiteSpacesIndices(in str : String) -> Array<Int> {
var indices: Array<Int> = []
let blanks: [UInt32] = [32, 10, 9] //these values correspond to space, new line, and tabulation respectively.
for (index, scalar) in str.unicodeScalars.enumerated() {
if blanks.contains(scalar.value) {
indices.append(index)
}
}
return indices
}
You can learn more about the Unicode scalar representation here.
Free function or instance method?
The whiteSpacesIndices
function seems more like a property on strings. It is appropriate for a String to know about the indices of white spaces (and new lines) within itself:
extension String {
var whiteSpaceIndices: [Int] {
var indices = [Int]()
let blanks: [UInt32] = [32, 10, 9]
for (index, scalar) in self.unicodeScalars.enumerated() {
if blanks.contains(scalar.value) {
indices.append(index)
}
}
return indices
}
}
And could be used like so:
"Hello world!".whiteSpaceIndices //[5]
"ä ö ü".whiteSpaceIndices //[1, 3]
8447
characters and1307
spaces, your code takes 0.5ms on my machine \$\endgroup\$