How add separator to string at every N characters in swift?
Swift 5.2 • Xcode 11.4 or later
extension Collection { func unfoldSubSequences(limitedTo maxLength: Int) -> UnfoldSequence<SubSequence,Index> { sequence(state: startIndex) { start in guard start < self.endIndex else { return nil } let end = self.index(start, offsetBy: maxLength, limitedBy: self.endIndex) ?? self.endIndex defer { start = end } return self[start..<end] } } func every(n: Int) -> UnfoldSequence<Element,Index> { sequence(state: startIndex) { index in guard index < endIndex else { return nil } defer { index = self.index(index, offsetBy: n, limitedBy: endIndex) ?? endIndex } return self[index] } } var pairs: [SubSequence] { .init(unfoldSubSequences(limitedTo: 2)) }}
extension StringProtocol where Self: RangeReplaceableCollection { mutating func insert<S: StringProtocol>(separator: S, every n: Int) { for index in indices.every(n: n).dropFirst().reversed() { insert(contentsOf: separator, at: index) } } func inserting<S: StringProtocol>(separator: S, every n: Int) -> Self { .init(unfoldSubSequences(limitedTo: n).joined(separator: separator)) }}
Testing
let str = "112312451"let final0 = str.unfoldSubSequences(limitedTo: 2).joined(separator: ":")print(final0) // "11:23:12:45:1"let final1 = str.pairs.joined(separator: ":")print(final1) // "11:23:12:45:1"let final2 = str.inserting(separator: ":", every: 2)print(final2) // "11:23:12:45:1\n"var str2 = "112312451"str2.insert(separator: ":", every: 2)print(str2) // "11:23:12:45:1\n"var str3 = "112312451"str3.insert(separator: ":", every: 3)print(str3) // "112:312:451\n"var str4 = "112312451"str4.insert(separator: ":", every: 4)print(str4) // "1123:1245:1\n"
I'll go for this compact solution (in Swift 4) :
let s = "11231245"let r = String(s.enumerated().map { $0 > 0 && $0 % 2 == 0 ? [":", $1] : [$1]}.joined())
You can make an extension and parameterize the stride and the separator so that you can use it for every value you want (In my case, I use it to dump 32-bit space-operated hexadecimal data):
extension String { func separate(every stride: Int = 4, with separator: Character = " ") -> String { return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined()) }}
In your case this gives the following results:
let x = "11231245"print (x.separate(every:2, with: ":")$ 11:23:12:45
Short and simple, add a let
or two if you want
extension String { func separate(every: Int, with separator: String) -> String { return String(stride(from: 0, to: Array(self).count, by: every).map { Array(Array(self)[$0..<min($0 + every, Array(self).count)]) }.joined(separator: separator)) }}
let a = "separatemepleaseandthankyou".separate(every: 4, with: " ")
a
is
sepa rate mepl ease andt hank you