Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Utility to functions to convert between camel case and underscore separated names
/**
* 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()
})

You shouldn't include digits when converting between camel and underscores, by definition there is no such thing as an upper case digit, and therefore it doesn't make sense to consider a digit a capitalised separate word.

eallik commented Jan 13, 2015

your algorithm doesn't correctly map _FOO_BAR to _FooBar and vice versa; here's my attempt at it:

def underscores2camel(name: String) = {
  assert(!(name endsWith "_"), "names ending in _ not supported by this algorithm")
  "[A-Za-z\\d]+_?|_".r.replaceAllIn(name, { x =>
    val x0 = x.group(0)
    if (x0 == "_") x0
    else x0.stripSuffix("_").toLowerCase.capitalize
  })
}
def camel2underscores(x: String) = {
  "_?[A-Z][a-z\\d]+".r.findAllMatchIn(x).map(_.group(0).toLowerCase).mkString("_")
}

ry4nz commented Mar 27, 2015

scala> camel2underscores("CamelCaseF")
res37: String = camel_case

@eallik, your algorithm returns "" for a non-camelcased string

scala> camel2underscores("foobar")
res1: String = ""

To avoid the leading _:

  def camelToUnderscores(name: String) = "[A-Z\\d]".r.replaceAllIn(name, {m =>
    if(m.end(0) == 1){
      m.group(0).toLowerCase()
    }else {
      "_" + m.group(0).toLowerCase()
    }
  })

asheshambasta commented Aug 11, 2016 edited

Maybe a little less concise but I prefer this;

def camel2Underscore(text: String) = text.drop(1).foldLeft(text.headOption.map(_.toLower + "") getOrElse "") {
  case (acc, c) if c.isUpper => acc + "_" + c.toLower
  case (acc, c) => acc + c
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment