With regex you could do something like this with thanks to OOPer's extension
Add a string extension that splits the string based on a regex pattern.
extension String {
func split(usingRegex pattern: String) -> [String] {
//### Crashes when you pass invalid `pattern`
let regex = try! NSRegularExpression(pattern: pattern)
let matches = regex.matches(in: self, range: NSRange(0..<utf16.count))
let ranges = [startIndex..<startIndex] + matches.map{Range($0.range, in: self)!} + [endIndex..<endIndex]
return (0...matches.count).map { String(self[ranges[$0].lowerBound..<ranges[$0+1].lowerBound]) }
}
}
Then split your string based on the pattern [0-9]{3}
3 numbers in a row.
let str = "001|apple|red|002|banana|yellow|003|grapes|purple|004|this|is|a|test|one|005|so|is|this"
let pattern = "[0-9]{3}"
let result = str.split(usingRegex: pattern)
var all:[[String]] = []
for row in result {
let split = row.split(separator: "|").map({ (substring) in
return String(substring)
})
if split.count != 0 {
all.append(split)
}
}
dump(all)
I tested this in a playground and got the following result:
▿ 5 elements
▿ 3 elements
- "001"
- "apple"
- "red"
▿ 3 elements
- "002"
- "banana"
- "yellow"
▿ 3 elements
- "003"
- "grapes"
- "purple"
▿ 6 elements
- "004"
- "this"
- "is"
- "a"
- "test"
- "one"
▿ 4 elements
- "005"
- "so"
- "is"
- "this"
If you decide you want to exclude the ID from the resulting arrays you can modify the extension return to the following:
return (0...matches.count).map { String(self[ranges[$0].upperBound..<ranges[$0+1].lowerBound]) }
This will switch the return range to use the upperBound
instead of lowerBound