Created
July 21, 2012 06:30
-
-
Save sidharthkuruvila/3154845 to your computer and use it in GitHub Desktop.
Utility to functions to convert between camel case and underscore separated names
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Takes a camel cased identifier name and returns an underscore separated | |
* name | |
* | |
* Example: | |
* camelToUnderscores("thisIsA1Test") == "this_is_a_1_test" | |
*/ | |
def camelToUnderscores(name: String) = "[A-Z\\d]".r.replaceAllIn(name, {m => | |
"_" + m.group(0).toLowerCase() | |
}) | |
/* | |
* Takes an underscore separated identifier name and returns a camel cased one | |
* | |
* Example: | |
* underscoreToCamel("this_is_a_1_test") == "thisIsA1Test" | |
*/ | |
def underscoreToCamel(name: String) = "_([a-z\\d])".r.replaceAllIn(name, {m => | |
m.group(1).toUpperCase() | |
}) |
@ruloweb This is nice but won't work if the two consecutive uppercase chars are at the start (ie. THisIsCamel) or if there are greater than two consecutive uppercase characters elsewhere (ie. ThisIsCAMel). Consequently, this will fail for converting all caps as well.
I adjusted the code to support the all caps case:
def camel2Snake(str: String): String = {
@tailrec
def camel2SnakeRec(s: String, output: String, lastUppercase: Boolean): String =
if (s.isEmpty) output
else {
val c = if (s.head.isUpper && !lastUppercase) "_" + s.head.toLower else s.head.toLower
camel2SnakeRec(s.tail, output + c, s.head.isUpper && !lastUppercase)
}
if (str.forall(_.isUpper)) str.map(_.toLower)
else {
camel2SnakeRec(str, "", true)
}
}
@amackillop, it doesnt't work for "THISIsADog" (it gives "t_hi_sis_adog")
i suggest the following code :
def camel2Snake(str: String): String = {
val headInUpperCase = str.takeWhile(c => c.isUpper || c.isDigit)
val tailAfterHeadInUppercase = str.dropWhile(c => c.isUpper || c.isDigit)
if (tailAfterHeadInUppercase.isEmpty) headInUpperCase.toLowerCase else {
val firstWord = if (!headInUpperCase.dropRight(1).isEmpty) {
headInUpperCase.last match {
case c: Any if (c.isDigit) => headInUpperCase
case _ => headInUpperCase.dropRight(1).toLowerCase
}
} else {
headInUpperCase.toLowerCase + tailAfterHeadInUppercase.takeWhile(c => c.isLower)
}
if (firstWord == str.toLowerCase) {
firstWord
} else {
s"${firstWord}_${camel2Snake(str.drop(firstWord.length))}"
}
}
}
@0dilon you version stack-overflows if the camelCase already contains an underscore.
e.g. camel2Snake("foo_BarBaz")
Late to the party, but iterate w/ Char
s seems fine too if you're ok w/ no handling -
s in the String
s
val camelToKebab: String => String = _.foldLeft("") {
case (acc, chr) if chr.isUpper => acc :+ '-' :+ chr.toLower
case (acc, chr) => acc :+ chr
}
val camelToSnake : String => String = _.foldLeft( "" ){ (acc, c) =>
( c.isUpper, acc.isEmpty, acc.takeRight(1) == "_" ) match {
case (true, false, false) => acc + "_" + c.toLower
case (true, _, _) => acc + c.toLower
case (false, _, _) => acc + c
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I prefer not to use regex, this approach runs in n time, it's tail recursive and does not convert consecutive upper chars, e.g. ThisIsCAmel -> this_is_camel: