CamelCase line splitting in space separated words in Swift

I would like to split the CamelCase line into space-separated words in a new line. Here is what I still have:

var camelCaps: String {
    guard self.count > 0 else { return self }
    var newString: String = ""

    let uppercase = CharacterSet.uppercaseLetters
    let first = self.unicodeScalars.first!
    newString.append(Character(first))
    for scalar in self.unicodeScalars.dropFirst() {
        if uppercase.contains(scalar) {
            newString.append(" ")
        }
        let character = Character(scalar)
        newString.append(character)
    }

    return newString
}

let aCamelCaps = "aCamelCaps"
let camelCapped = aCamelCaps.camelCaps // Produce: "a Camel Caps"

let anotherCamelCaps = "ÄnotherCamelCaps"
let anotherCamelCapped = anotherCamelCaps.camelCaps // "Änother Camel Caps"

I am inclined to suspect that perhaps this is not the most efficient way of converting into space-separated words if I call it in a narrow loop, or 1000 times. Are there any more efficient ways to do this in Swift?

[Edit 1:] The solution I need should remain common for Unicode scalars, and not just for Roman ASCII "A..Z".

[Edit 2:] The decision should also omit the first letter, that is, Do not put a space before the first letter.

[Edit 3:] Updated Swift 4 syntax and added uppercaseLetters caching, which improves performance in very long lines and narrow loops.

+11
9

MacBook, :

import Foundation

extension String {

    var camelCaps: String {
        var newString: String = ""

        let upperCase = CharacterSet.uppercaseLetters
        for scalar in self.unicodeScalars {
            if upperCase.contains(scalar) {
                newString.append(" ")
            }
            let character = Character(scalar)
            newString.append(character)
        }

        return newString
    }

    var camelCaps2: String {
        var newString: String = ""

        let upperCase = CharacterSet.uppercaseLetters
        var range = self.startIndex..<self.endIndex
        while let foundRange = self.rangeOfCharacter(from: upperCase,range: range) {
            newString += self.substring(with: range.lowerBound..<foundRange.lowerBound)
            newString += " "
            newString += self.substring(with: foundRange)

            range = foundRange.upperBound..<self.endIndex
        }
        newString += self.substring(with: range)

        return newString
    }

    var camelCaps3: String {
        struct My {
            static let regex = try! NSRegularExpression(pattern: "[A-Z]")
        }
        return My.regex.stringByReplacingMatches(in: self, range: NSRange(0..<self.utf16.count), withTemplate: " $0")
    }
}
let aCamelCaps = "aCamelCaps"

assert(aCamelCaps.camelCaps == aCamelCaps.camelCaps2)
assert(aCamelCaps.camelCaps == aCamelCaps.camelCaps3)

let t0 = Date().timeIntervalSinceReferenceDate

for _ in 0..<1_000_000 {
    let aCamelCaps = "aCamelCaps"

    let camelCapped = aCamelCaps.camelCaps
}

let t1 = Date().timeIntervalSinceReferenceDate
print(t1-t0) //->4.78703999519348

for _ in 0..<1_000_000 {
    let aCamelCaps = "aCamelCaps"

    let camelCapped = aCamelCaps.camelCaps2
}

let t2 = Date().timeIntervalSinceReferenceDate
print(t2-t1) //->10.5831440091133

for _ in 0..<1_000_000 {
    let aCamelCaps = "aCamelCaps"

    let camelCapped = aCamelCaps.camelCaps3
}

let t3 = Date().timeIntervalSinceReferenceDate
print(t3-t2) //->14.2085000276566

( . , CommandLine.)

+8

Swift 2.x

extension String {

    func camelCaseToWords() -> String {

        return unicodeScalars.reduce("") {

            if NSCharacterSet.uppercaseLetterCharacterSet().characterIsMember(uint_least16_t($1.value)) {
                return ($0 + " " + String($1))
            }
            else {

                return ($0 + String($1))
            }
        }
    }
}

Swift 3.x

extension String {

    func camelCaseToWords() -> String {

        return unicodeScalars.reduce("") {

            if CharacterSet.uppercaseLetters.contains($1) {

                return ($0 + " " + String($1))
            }
            else {

                return $0 + String($1)
            }
        }
    }
}

- :)

+11

, , PA .
, , upper camel case (, "DuckDuckGo" ), .
, , Swift 3.x, , :

extension String {

    func camelCaseToWords() -> String {
        return unicodeScalars.reduce("") {
            if CharacterSet.uppercaseLetters.contains($1) {
                if $0.characters.count > 0 {
                    return ($0 + " " + String($1))
                }
            }
            return $0 + String($1)
        }
    }
}
+5

One Line

@aircraft, LOC!

// Swift 5 (and probably 4?)
extension String {
    func titleCase() -> String {
        return self
            .replacingOccurrences(of: "([A-Z])",
                                  with: " $1",
                                  options: .regularExpression,
                                  range: range(of: self))
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .capitalized // If input is in llamaCase
    }
}

JS.

snake_case → CamelCase .

P.P.S. New Swift ( 5.1), @busta startIndex..<endIndex range(of: self). , !

+5

... AmitaiB

extension String {
    func titlecased() -> String {
        return self.replacingOccurrences(of: "([A-Z])", with: " $1", options: .regularExpression, range: self.range(of: self))
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .capitalized
    }
}
+5

( CharacterSet), , , .

var differentCamelCaps: String {

    var newString: String = ""

    for eachCharacter in self.characters {
        if (eachCharacter >= "A" && eachCharacter <= "Z") == true {
            newString.append(" ")
        }
        newString.append(eachCharacter)
    }

    return newString
}
+3

, Regular Expressions.

 extension String {
    func replace(regex: NSRegularExpression, with replacer: (_ match:String)->String) -> String {
    let str = self as NSString
    let ret = str.mutableCopy() as! NSMutableString

    let matches = regex.matches(in: str as String, options: [], range: NSMakeRange(0, str.length))
    for match in matches.reversed() {
        let original = str.substring(with: match.range)
        let replacement = replacer(original)
        ret.replaceCharacters(in: match.range, with: replacement)
    }
        return ret as String
    }
}

let camelCaps = "aCamelCaps"  // there are 3 Capital character
let pattern = "[A-Z]"
let regular = try!NSRegularExpression(pattern: pattern)
let camelCapped:String = camelCaps.replace(regex: regular) { " \($0)" }
print("Uppercase characters replaced: \(camelCapped)")
+2
extension String {
    func titlecased() -> String {
        return self
            .replacingOccurrences(of: "([a-z])([A-Z](?=[A-Z])[a-z]*)", with: "$1 $2", options: .regularExpression)
            .replacingOccurrences(of: "([A-Z])([A-Z][a-z])", with: "$1 $2", options: .regularExpression)
            .replacingOccurrences(of: "([a-z])([A-Z][a-z])", with: "$1 $2", options: .regularExpression)
            .replacingOccurrences(of: "([a-z])([A-Z][a-z])", with: "$1 $2", options: .regularExpression)
    }
}

 "ThisStringHasNoSpacesButItDoesHaveCapitals"
 "IAmNotAGoat"
 "LOLThatsHilarious!"
 "ThisIsASMSMessage"

Out

"This String Has No Spaces But It Does Have Capitals" 
"I Am Not A Goat" 
"LOL Thats Hilarious!" 
"This Is ASMS Message" // (Difficult tohandle single letter words when they are next to acronyms.)

+1

Swift 5

extension String {

    func camelCaseToWords() -> String {
        return unicodeScalars.reduce("") {
            if CharacterSet.uppercaseLetters.contains($1) {
                if $0.count > 0 {
                    return ($0 + " " + String($1))
                }
            }
            return $0 + String($1)
        }
    }
}
0
source

Source: https://habr.com/ru/post/1664623/


All Articles