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 < endIndex else { return nil }
            let end = index(start, offsetBy: maxLength, limitedBy: endIndex) ?? 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 { let _ = formIndex(&index, offsetBy: n, limitedBy: 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"

Leave a Comment