LoginSignup
17
13

More than 5 years have passed since last update.

Swift 4 でキャメルケースとスネークケースを変換する String 拡張

Last updated at Posted at 2015-04-22

2017-12-16 追記

Swift 4 でも動くように書き直しました。いや〜、様変わりしましたね。

標準ライブラリにない……!!!

ウギャーーー!よく使いそうなのに!
ケースのポリシーが違うシステム間でデータをやりとりするとき(json でデータをやりとりするときとか)、変数名を自動で変換したかったのでしこしこ書いた。

追記: 今は Codable という便利な仕組みがあるので、json でやり取りしたいときのケース変換はそっちを使うほうが良いでしょう。

コード

スネークケース → キャメルケース

// Swift 4 版 (String の extension として実装)
extension String {
    // set `lower = false` in case you want "UpperCamel" output.
    func camelized(lower: Bool = true) -> String {
        guard self != "" else { return self }

        let words = lowercased().split(separator: "_").map({ String($0) })
        let firstWord: String = words.first ?? ""

        let camel: String = lower ? firstWord : String(firstWord.prefix(1).capitalized) + String(firstWord.suffix(from: index(after: startIndex)))
        return words.dropFirst().reduce(into: camel, { camel, word in
            camel.append(String(word.prefix(1).capitalized) + String(word.suffix(from: index(after: startIndex))))
        })
    }
}
// Swift 2 版
// set `lower = false` in case you want "UpperCamel" output.
func snakeIntoCamel (snake:String, lower:Bool=true) -> String {
    let pattern = "(\\w{0,1})_"
    var camel = snake.capitalizedString.stringByReplacingOccurrencesOfString(pattern, withString: "$1",
        options: NSStringCompareOptions.RegularExpressionSearch, range: nil)

    if lower {
        // make the first letter lower case
        let head = snake.substringToIndex(advance(snake.startIndex, 1))
        camel.replaceRange(camel.startIndex...camel.startIndex, with: head.lowercaseString)
    }

    return camel
}

キャメルケース → スネークケース

// Swift 4 版 (String の extension として実装)
extension String {
    var snakenized: String {
        // Ensure the first letter is capital
        let head = String(prefix(1))
        let tail = String(suffix(count - 1))
        let upperCased = head.uppercased() + tail

        let input = upperCased

        // split input string into words with Capital letter
        let pattern = "[A-Z]+[a-z,\\d]*"
        guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
            return ""
        }

        var words:[String] = []

        regex.matches(in: input, options: [], range: NSRange.init(location: 0, length: count)).forEach { match in
            if let range = Range(match.range(at: 0), in: self) {
                words.append(String(self[range]).lowercased())
            }
        }

        return words.joined(separator: "_")
    }
}
// Swift 2 版
func camelIntoSnake (camel:String) -> String {
    // ensure the first letter is capital
    let head = camel.substringToIndex(advance(camel.startIndex, 1))
    var upperCased = camel
    upperCased.replaceRange(camel.startIndex...camel.startIndex, with: head.uppercaseString)

    var input = upperCased as NSString

    // split input string into words
    let pattern = "[A-Z]+[a-z,\\d]*"
    let regex = NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.allZeros, error: nil)

    var words:[String] = []

    if let matches = regex?.matchesInString(input as String, options: NSMatchingOptions.allZeros, range: NSRange(location: 0, length: input.length)) {
        for match in matches {
            for var i = 0; i < match.numberOfRanges; ++i {
                // make every word in lower case
                words.append(input.substringWithRange(match.rangeAtIndex(i)).lowercaseString)
            }
        }
    }

    return join("_", words)
}

Swift、というか Foundation フレームワークでは正規表現がめっちゃめんどくさいですな。。。
目がぱちぱちするね!

参考

http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/
http://blog.mogmet.com/swift-regular-expression-replace/

17
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13