How do I get letters and integers from a single string, considering that 2 (or more) integers can be together and should be treated as a single integer?
So let's take an string "a2bc31d"
as an input, I want the output to be an array either ["a","2","bc","31","d"]
or ["a","2","b","c","31","d"]
So far I have tried this:
let input = "a2bc31d"
let intArr = input.components(separatedBy: CharacterSet.decimalDigits.inverted) // produces ["", "2", "", "31", ""]
var stringArr = input.components(separatedBy: CharacterSet.letters.inverted).filter({ $0 != "" }) // produces ["a", "bc", "d"]
var newArr = intArr
// Then merge both arrays
for (index,string) in intArr.enumerated() {
if string == "" {
newArr[index] = stringArr.first ?? ""
stringArr.removeFirst()
}
}
print(newArr) //prints ["a", "2", "bc", "31", "d"]
The problem is that a minimum change to the input to something like "ab2bc31d"
then it crashes because the arrays are not created the same.
The stringArr is fine, it is now ["ab","bc","d"]
, but the intArr is now ["","","2","","31",""]
instead of ["","2","","31",""]
. So sometimes is creating 1 string for a block of letters, and sometimes is creation 1 string for each letter, which makes my logic to merge both arrays to crash.
components(separatedBy:
is giving different outputs for the same kind of strings?Using a regular expression, this can be done in a one-liner.
let input = "a2bc31d"
let matches = input.matches(of: /\D+|\d+/).map(\.output)
print(matches)
The regex /\D+|\d+/
matches either a sequence of non-digits, or a sequence of digits. matches(of:)
finds all such sequences.
The result matches
is a [Substring]
. Feel free to convert that to a [String]
if you wish:
let strings = matches.map(String.init)