I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Camel case and snake case

From Rosetta Code
Camel case and snake case is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Two common conventions for naming of computer program variables are Snake Case and Camel Case.

Snake case variables are generally all lower case, with an underscore between words in the variable, as in snake_case_variable'. Camel case variables are generally lower case first (except in some Pascal conventions or with class names in many other languages), with captalization of the initial letter of the words within the variable, as in 'camelCaseVariable'.

Leading underscores are not used in such variables except as part of a different naming convention, usually for special internal or system variables. White space is not permitted as part of camel case or snake case variable names.

Task
  • Write two functions, one to change snake case to camel case and one to change camel case to snake case. If possible, generalize the function enough to apply to strings containing spaces between words or a `-` dash between words, assuming that in those cases a space or hyphen is a also a separator character, like `_`, for the purpose of creating a new variable name. Leading or trailing whitespace may be ignored.
  • Show the results on changing to both snake case and camel case for each of the following strings:
 
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "
 
Related tasks


ALGOL 68[edit]

Treating space, - and _ as equivalent "break" characters (as in most of the other samples) and adding kebab case (as in the Raku sample) and resisting the urge to add "space case" for languages like Algol 68 where (insignificant) spaces can appear in identifiers...

BEGIN # convert camel case to and from snake case #
# returns c converted to uppercase if it is lowercase, c otherwise #
OP TOUPPER = ( CHAR c )STRING:
IF c >= "a" AND c <= "z" THEN REPR( ( ABS c - ABS "a" ) + ABS "A" ) ELSE c FI;
# returns c converted to lowercase if it is uppercase, c otherwise #
OP TOLOWER = ( CHAR c )STRING:
IF c >= "A" AND c <= "Z" THEN REPR( ( ABS c - ABS "A" ) + ABS "a" ) ELSE c FI;
# returns the camel case identifier c in snake case #
OP CAMELTOSNAKE = ( STRING c )STRING: c CAMELTOBREAK "_";
# returns the camel case identifier c in kebab case #
OP CAMELTOKEBAB = ( STRING c )STRING: c CAMELTOBREAK "-";
# returns TRUE if c is a "break" character ( " ", "-" or "_" ), FALSE otherwise #
OP ISBREAK = ( CHAR c )BOOL: c = " " OR c = "-" OR c = "_";
# returns the indentifier id (which is assumed to be in Camel case) #
# converted to snake or kebab case depending on break char #
PRIO CAMELTOBREAK = 9; # CAMELTOBREAK is dyadic so need a priority #
OP CAMELTOBREAK = ( STRING id, CHAR break char )STRING:
BEGIN
STRING result := "";
STRING orig = TRIM id; # remove leading and trailing spaces #
BOOL first := TRUE;
INT c pos := LWB orig;
WHILE c pos <= UPB orig DO
CHAR c = orig[ c pos ];
IF c >= "A" AND c <= "Z" THEN
# have an uppercase letter #
IF NOT first THEN result +:= break char FI;
result +:= TOLOWER c
ELIF ISBREAK c THEN
# replace one or more spaces and break characters by a single break #
BOOL have break := TRUE;
WHILE c pos <= UPB orig AND have break DO
IF have break := ISBREAK orig[ c pos ] THEN c pos +:= 1 FI
OD;
IF c pos <= UPB orig THEN
# the identifier didn't end wih a break #
result +:= break char + TOLOWER orig[ c pos ]
FI
ELSE
# lowercase or punctuation #
result +:= c
FI;
first := FALSE;
c pos +:= 1
OD;
result
END # CAMELTOBREAK # ;
# returns the identifier id ( which is assumed to be in snake/kebab/space case ) #
# converted to Camel case #
OP TOCAMEL = ( STRING id )STRING:
BEGIN
STRING result := "";
STRING orig = TRIM id; # remove leading and trailing spaces #
INT c pos := LWB orig;
WHILE c pos <= UPB orig DO
CHAR c = orig[ c pos ];
IF c >= "A" AND c <= "Z" THEN
# uppercase letter - leave as is #
result +:= c
ELIF NOT ISBREAK c THEN
# not a break - convert to lower case if necessary and move to the next #
result +:= TOLOWER c;
ELSE
# have a separator - skip all subsequent separators and upcase the follower #
BOOL have break := TRUE;
WHILE c pos <= UPB orig AND have break DO
IF have break := ISBREAK orig[ c pos ] THEN c pos +:= 1 FI
OD;
IF c pos <= UPB orig THEN
# the identifier didn't end with a break character #
result +:= TOUPPER orig[ c pos ]
FI
FI;
c pos +:= 1
OD;
result
END # TOCAMEL # ;
# returns s left-padded to len characters or s if s is already that long #
PRIO PAD = 9;
OP PAD = ( INT len, STRING s )STRING:
IF INT s len = ( UPB s - LWB s ) + 1;
s len >= len
THEN s
ELSE
STRING result := s;
FOR i FROM s len + 1 TO len DO " " +=: result OD;
result
FI # PAD # ;
# returns s with leading and trailing spaces removed #
OP TRIM = ( STRING s )STRING:
BEGIN
INT left := LWB s;
INT right := UPB s;
WHILE IF left > right THEN FALSE ELSE s[ left ] = " " FI DO left +:= 1 OD;
WHILE IF right < left THEN FALSE ELSE s[ right ] = " " FI DO right -:= 1 OD;
s[ left : right ]
END # TRIM # ;
# task test cases #
[]STRING identifier = ( "snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis"
, "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "
);
print( ( "to snake case:", newline ) );
FOR i FROM LWB identifier TO UPB identifier DO
print( ( 40 PAD identifier[ i ], " -> ", CAMELTOSNAKE identifier[ i ], newline ) )
OD;
print( ( "to Camel case:", newline ) );
FOR i FROM LWB identifier TO UPB identifier DO
print( ( 40 PAD identifier[ i ], " -> ", TOCAMEL identifier[ i ], newline ) )
OD;
print( ( "to kebab case:", newline ) );
FOR i FROM LWB identifier TO UPB identifier DO
print( ( 40 PAD identifier[ i ], " -> ", CAMELTOKEBAB identifier[ i ], newline ) )
OD
END
Output:
to snake case:
                               snakeCase -> snake_case
                              snake_case -> snake_case
                        variable_10_case -> variable_10_case
                          variable10Case -> variable10_case
                           ╔ørgo rE tHis -> ╔ørgo_r_e_t_his
                           hurry-up-joe! -> hurry_up_joe!
       c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
                                spaces   -> spaces
to Camel case:
                               snakeCase -> snakeCase
                              snake_case -> snakeCase
                        variable_10_case -> variable10Case
                          variable10Case -> variable10Case
                           ╔ørgo rE tHis -> ╔ørgoRETHis
                           hurry-up-joe! -> hurryUpJoe!
       c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                                spaces   -> spaces
to kebab case:
                               snakeCase -> snake-case
                              snake_case -> snake-case
                        variable_10_case -> variable-10-case
                          variable10Case -> variable10-case
                           ╔ørgo rE tHis -> ╔ørgo-r-e-t-his
                           hurry-up-joe! -> hurry-up-joe!
       c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy-flag-day/12.doc
                                spaces   -> spaces

Factor[edit]

In my interpretation of the task, leading/trailing whitespace should be ignored, not trimmed. And non-leading/trailing whitespace should be dealt with the same way as underscores and hyphens. Although the task says nothing about numbers, I chose to treat letter->number and number->letter transitions the same way as lower->upper for the sake of converting to snake case.

Works with: Factor version 0.99 2021-06-02
USING: formatting kernel math regexp sequences splitting
splitting.extras unicode ;
 
! ignore leading/trailing whitespace
: preserve ( str quot -- newstr )
[ [ blank? ] split-head [ blank? ] split-tail swap ] dip
call glue ; inline
 
: >snake ( str -- newstr )
[
R/ (\p{lower}\p{upper}|\d\p{alpha}|\p{alpha}\d)/
[ 1 short cut >lower "_" glue ] re-replace-with
R/ [\s-]/ "_" re-replace
] preserve ;
 
: capitalize ( str -- newstr ) 1 short cut swap >upper prepend ;
 
: >camel ( str -- newstr )
[
"\s_-" split harvest 1 short cut
[ capitalize ] map append "" join
] preserve ;
 
: test ( str -- )
dup >snake over dup >camel
"%u >snake %u\n%u >camel %u\n" printf ;
 
{
"snakeCase" "snake_case" "variable_10_case" "variable10Case"
"ɛrgo rE tHis" "hurry-up-joe!"
"c://my-docs/happy_Flag-Day/12.doc" " spaces "
" internal space "
} [ test ] each
Output:
"snakeCase" >snake "snake_case"
"snakeCase" >camel "snakeCase"
"snake_case" >snake "snake_case"
"snake_case" >camel "snakeCase"
"variable_10_case" >snake "variable_10_case"
"variable_10_case" >camel "variable10Case"
"variable10Case" >snake "variable_10_case"
"variable10Case" >camel "variable10Case"
"ɛrgo rE tHis" >snake "ɛrgo_r_e_t_his"
"ɛrgo rE tHis" >camel "ɛrgoRETHis"
"hurry-up-joe!" >snake "hurry_up_joe!"
"hurry-up-joe!" >camel "hurryUpJoe!"
"c://my-docs/happy_Flag-Day/12.doc" >snake "c://my_docs/happy_Flag_Day/12.doc"
"c://my-docs/happy_Flag-Day/12.doc" >camel "c://myDocs/happyFlagDay/12.doc"
"  spaces  " >snake "  spaces  "
"  spaces  " >camel "  spaces  "
"   internal space   " >snake "   internal_space   "
"   internal space   " >camel "   internalSpace   "

jq[edit]

Adapted from Wren

Works with: jq

Works with gojq, the Go implementation of jq

Preliminaries

def isUpper: explode[0] | 65 <= . and . <= 90;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
 
# "White space is not permitted as part of camel case or snake case variable names."
def trim: sub("^\\s+";"") | sub("\\s+$";"");

Camel and Snake

def toCamel:
trim as $snake
| { camel: "", underscore : false}
| reduce ($snake|explode[]|[.]|implode) as $c (.;
if ["_", "-", " "]|index($c)
then .underscore = true
elif .underscore
then .camel += ($c|ascii_upcase)
| .underscore = false
else .camel += $c
end)
| .camel;
 
def toSnake:
(trim | gsub("\\s"; "_")) as $camel
| reduce ($camel|explode[1:][]|[.]|implode) as $c (
$camel[0:1];
if $c|isUpper
then ($c|ascii_downcase) as $lc
| if (.[-1:] | (. == "_" or . == "-"))
then . + $lc
else . + "_" + $lc
end
else . + $c
end );
 
def tests: [
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "
];
 
" === to_snake_case ===",
(tests[] | "\(lpad(33)) -> \(toSnake)"),
"",
" === toCamelCase ===",
(tests[] | "\(lpad(33)) -> \(toCamel)")
Output:
                          === to_snake_case ===
                        snakeCase -> snake_case
                       snake_case -> snake_case
                 variable_10_case -> variable_10_case
                   variable10Case -> variable10_case
                     ɛrgo rE tHis -> ɛrgo_r_e_t_his
                    hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
                         spaces   -> spaces

                          === toCamelCase ===
                        snakeCase -> snakeCase
                       snake_case -> snakeCase
                 variable_10_case -> variable10Case
                   variable10Case -> variable10Case
                     ɛrgo rE tHis -> ɛrgoRETHis
                    hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                         spaces   -> spaces


Julia[edit]

#=
Regex based variable name convention change string functions.
`sep` is the separator targeted for change from (to camel case) or to (to snake case)
`allsep` is the separators other than `sep` that may be changed to `sep`
`lcmiddle` is a boolean to set whether caps within camel case words are made lowercase
=#
 
function snakeToCamelCase(s; sep=r"[_]+", lcmiddle=false)
isempty(s) && return s
words = split(strip(s), sep)
return lowercasefirst(join(uppercasefirst.(lcmiddle ? lowercase.(words) : words)))
end
 
spaceToCamelCase(s) = snakeToCamelCase(s; sep=r"\s+")
kebabToCamelCase(s) = snakeToCamelCase(s; sep=r"[\-]+")
periodToCamelCase(s) = snakeToCamelCase(s; sep=r"[\.]+")
allsepToCamelCase(s) = snakeToCamelCase(s; sep=r"[ \-_\.]+")
lowermiddle_allsepToCamelCase(s) = snakeToCamelCase(s; sep=r"[ \-_\.]+", lcmiddle=true)
 
function camel_to_snake_case(s; sep="_", insep=sep, allsep=r"_+", lcmiddle=true)
s = isempty(s) ? (return s) : lowercasefirst(strip(s))
s = replace(s, r"[A-Z]+" => x -> sep * (lcmiddle ? lowercase(x) : lowercasefirst(x)))
return replace(s, allsep => sep)
end
 
preserve_midcaps_camel_to_snake_case(s) = camel_to_snake_case(s; lcmiddle=false)
allsep_to_snake_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+")
allsep_to_kebab_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep="-")
allsep_to_space_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep=" ")
allsep_to_period_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep=".")
allsep_to_slash_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep="/")
 
for f in [
snakeToCamelCase,
spaceToCamelCase,
kebabToCamelCase,
periodToCamelCase,
allsepToCamelCase,
lowermiddle_allsepToCamelCase,
camel_to_snake_case,
preserve_midcaps_camel_to_snake_case,
allsep_to_snake_case,
allsep_to_kebab_case,
allsep_to_space_case,
allsep_to_period_case,
allsep_to_slash_case,
]
println("Testing function $f:")
 
for teststring in [
"snakeCase",
"snake_case",
"snake-case",
"snake case",
"snake CASE",
"snake.case",
"variable_10_case",
"variable10Case",
"ɛrgo rE tHis",
"hurry-up-joe!",
"c://my-docs/happy_Flag-Day/12.doc",
" spaces ",
]
println(lpad(teststring, 36), " => ", f(teststring))
end
println()
end
 
Output:
Testing function snakeToCamelCase:
                           snakeCase  =>  snakeCase     
                          snake_case  =>  snakeCase     
                          snake-case  =>  snake-case    
                          snake case  =>  snake case    
                          snake CASE  =>  snake CASE    
                          snake.case  =>  snake.case    
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                             spaces   =>  spaces

Testing function spaceToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                             spaces   =>  spaces

Testing function kebabToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snakeCase
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                             spaces   =>  spaces

Testing function periodToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12Doc
                             spaces   =>  spaces

Testing function allsepToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function lowermiddle_allsepToCamelCase:
                           snakeCase  =>  snakecase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCase
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10case
                        ɛrgo rE tHis  =>  ɛrgoReThis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function preserve_midcaps_camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _cASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake_case
                          snake case  =>  snake_case
                          snake CASE  =>  snake_case
                          snake.case  =>  snake_case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo_r_e_t_his
                       hurry-up-joe!  =>  hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my_docs/happy_flag_day/12_doc
                             spaces   =>  spaces

Testing function allsep_to_kebab_case:
                           snakeCase  =>  snake-case
                          snake_case  =>  snake-case
                          snake-case  =>  snake-case
                          snake case  =>  snake-case
                          snake CASE  =>  snake-case
                          snake.case  =>  snake-case
                    variable_10_case  =>  variable-10-case
                      variable10Case  =>  variable10-case
                        ɛrgo rE tHis  =>  ɛrgo-r-e-t-his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy-flag-day/12-doc
                             spaces   =>  spaces

Testing function allsep_to_space_case:
                           snakeCase  =>  snake case
                          snake_case  =>  snake case
                          snake-case  =>  snake case
                          snake case  =>  snake case
                          snake CASE  =>  snake case
                          snake.case  =>  snake case
                    variable_10_case  =>  variable 10 case
                      variable10Case  =>  variable10 case
                        ɛrgo rE tHis  =>  ɛrgo r e t his
                       hurry-up-joe!  =>  hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my docs/happy flag day/12 doc
                             spaces   =>  spaces

Testing function allsep_to_period_case:
                           snakeCase  =>  snake.case
                          snake_case  =>  snake.case
                          snake-case  =>  snake.case
                          snake case  =>  snake.case
                          snake CASE  =>  snake.case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable.10.case
                      variable10Case  =>  variable10.case
                        ɛrgo rE tHis  =>  ɛrgo.r.e.t.his
                       hurry-up-joe!  =>  hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my.docs/happy.flag.day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_slash_case:
                           snakeCase  =>  snake/case
                          snake_case  =>  snake/case
                          snake-case  =>  snake/case
                          snake case  =>  snake/case
                          snake CASE  =>  snake//case
                          snake.case  =>  snake/case
                    variable_10_case  =>  variable/10/case
                      variable10Case  =>  variable10/case
                        ɛrgo rE tHis  =>  ɛrgo/r/e/t/his
                       hurry-up-joe!  =>  hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my/docs/happy//flag//day/12/doc
                             spaces   =>  spaces

Perl[edit]

#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Camel_case_and_snake_case
use warnings;
 
my @words = (
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "#rgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "
);
 
sub tosnake
{
shift =~ s/^ +| +$//gr =~ s/[A-Z]/_\l$&/gr =~ tr/ -/_/r =~ s/__+/_/gr;
}
 
sub tocamel
{
shift =~ s/^ +| +$//gr =~ s/[ _-]([a-z0-9])/\u$1/gir;
}
 
print "to snake case\n\n";
for my $word ( @words )
{
printf "%35s -> %s\n", $word, tosnake($word);
}
 
print "\nto camel case\n\n";
for my $word ( @words )
{
printf "%35s -> %s\n", $word, tocamel($word);
}
Output:
to snake case

                          snakeCase -> snake_case
                         snake_case -> snake_case
                   variable_10_case -> variable_10_case
                     variable10Case -> variable10_case
                       #rgo rE tHis -> #rgo_r_e_t_his
                      hurry-up-joe! -> hurry_up_joe!
  c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
                           spaces   -> spaces

to camel case

                          snakeCase -> snakeCase
                         snake_case -> snakeCase
                   variable_10_case -> variable10Case
                     variable10Case -> variable10Case
                       #rgo rE tHis -> #rgoRETHis
                      hurry-up-joe! -> hurryUpJoe!
  c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                           spaces   -> spaces

Phix[edit]

with javascript_semantics
function to_snake_case(string s)
    string snake = substitute(trim(s)," ","_")
    for i=length(snake) to 1 by -1 do
        if isupper(snake[i]) then
            snake[i..i] = '_'&lower(snake[i])
        end if
    end for
    return snake
end function

function toCamelCase(string s)
    string camel = substitute_all(trim(s),"- ","__")
    for i=length(camel)-1 to 1 by -1 do
        if camel[i]='_' then
            camel[i..i+1] = upper(camel[i+1..i+1])
        end if
    end for
    return camel
end function
 
constant tests = {"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ergo rE tHis",
                  "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "}
procedure test(string title, integer fn)
    printf(1,title)
    for i=1 to length(tests) do
        printf(1,"%33s ===> %s\n", {tests[i], fn(tests[i])})
    end for
end procedure
test("                          === to_snake_case ===\n",to_snake_case)
test("\n                          === toCamelCase ===\n",toCamelCase)
Output:
                          === to_snake_case ===
                        snakeCase ===> snake_case
                       snake_case ===> snake_case
                 variable_10_case ===> variable_10_case
                   variable10Case ===> variable10_case
                     ergo rE tHis ===> ergo_r_e_t_his
                    hurry-up-joe! ===> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ===> c://my-docs/happy__flag-_day/12.doc
                         spaces   ===> spaces

                          === toCamelCase ===
                        snakeCase ===> snakeCase
                       snake_case ===> snakeCase
                 variable_10_case ===> variable10Case
                   variable10Case ===> variable10Case
                     ergo rE tHis ===> ergoRETHis
                    hurry-up-joe! ===> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc ===> c://myDocs/happyFlagDay/12.doc
                         spaces   ===> spaces

Python[edit]

""" https://rosettacode.org/wiki/Camel_case_and_snake_case """
 
import re
 
def snakeToCamelCase(nam, sep='[_]+', lcmiddle=False):
""" convert snake '_' separator case to camel case """
if nam == '':
return nam
words = re.split(sep, nam.strip())
if lcmiddle:
words = [w.lower() for w in words]
words[1:] = [w[0].upper() + w[1:] for w in words[1:] if len(w) > 0]
return ''.join(words)
 
 
def spaceToCamelCase(nam):
""" convert space case to camel case """
return snakeToCamelCase(nam, sep='\s+')
 
def kebabToCamelCase(nam):
""" convert kebab '-' case to camel case """
return snakeToCamelCase(nam, sep='[\-]+')
 
def periodToCamelCase(nam):
""" convert period '.' case to camel case """
return snakeToCamelCase(nam, sep='[\.]+')
 
def allsepToCamelCase(nam):
""" convert all separators in allsep to camel case """
return snakeToCamelCase(nam, sep='[ \-_\.]+')
 
def lowermiddle_allsepToCamelCase(nam):
""" convert all separators to camel case, and all but word starts to lowercase """
return snakeToCamelCase(nam, sep='[ \-_\.]+', lcmiddle=True)
 
def camel_to_snake_case(nam, sep='_', allsep='[_]+', lcmiddle=True):
""" convert camel case to snake case (separate with '_') """
nam = re.sub('([A-Z]+)', sep + r"\1", nam.strip())
sep1 = '\\' + sep if sep == '.' else sep
if lcmiddle:
nam = sep.join([w.lower() for w in nam.split(sep1) if len(w) > 0])
else:
nam = sep.join([w[0].lower() + w[1:] for w in nam.split(sep1) if len(w) > 0])
return re.sub(allsep, sep, nam)
 
def preserve_midcaps_camel_to_snake_case(nam):
return camel_to_snake_case(nam, lcmiddle=False)
 
def allsep_to_snake_case(nam):
return camel_to_snake_case(nam, allsep='[ \-\._]+')
 
def allsep_to_kebab_case(nam):
return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='-')
 
def allsep_to_space_case(nam):
return camel_to_snake_case(nam, allsep='[ \-\._]+', sep=' ')
 
def allsep_to_period_case(nam):
return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='.')
 
def allsep_to_slash_case(nam):
return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='/')
 
for f in [
snakeToCamelCase,
spaceToCamelCase,
kebabToCamelCase,
periodToCamelCase,
allsepToCamelCase,
lowermiddle_allsepToCamelCase,
camel_to_snake_case,
preserve_midcaps_camel_to_snake_case,
allsep_to_snake_case,
allsep_to_kebab_case,
allsep_to_space_case,
allsep_to_period_case,
allsep_to_slash_case]:
print(f"Testing function {f}:")
for teststring in [
"snakeCase",
"snake_case",
"snake-case",
"snake case",
"snake CASE",
"snake.case",
"variable_10_case",
"variable10Case",
"ɛrgo rE tHis",
"hurry-up-joe!",
"c://my-docs/happy_Flag-Day/12.doc",
" spaces "]:
print(teststring.rjust(36), " => ", f(teststring))
print()
 
Output:
Testing function <function snakeToCamelCase at 0x000001F17C25AC10>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                             spaces   =>  spaces

Testing function <function spaceToCamelCase at 0x000001F17C25AA60>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                             spaces   =>  spaces

Testing function <function kebabToCamelCase at 0x000001F17C25ADC0>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snakeCase
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                             spaces   =>  spaces

Testing function <function periodToCamelCase at 0x000001F17C25AE50>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12Doc
                             spaces   =>  spaces

Testing function <function allsepToCamelCase at 0x000001F17C25AEE0>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function <function lowermiddle_allsepToCamelCase at 0x000001F17C25AF70>:
                           snakeCase  =>  snakecase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCase
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10case
                        ɛrgo rE tHis  =>  ɛrgoReThis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function <function camel_to_snake_case at 0x000001F17C262040>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function <function preserve_midcaps_camel_to_snake_case at 0x000001F17C2620D0>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _cASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function <function allsep_to_snake_case at 0x000001F17C262160>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake_case
                          snake case  =>  snake_case
                          snake CASE  =>  snake_case
                          snake.case  =>  snake_case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo_r_e_t_his
                       hurry-up-joe!  =>  hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my_docs/happy_flag_day/12_doc
                             spaces   =>  spaces

Testing function <function allsep_to_kebab_case at 0x000001F17C2621F0>:
                           snakeCase  =>  snake-case
                          snake_case  =>  snake-case
                          snake-case  =>  snake-case
                          snake case  =>  snake-case
                          snake CASE  =>  snake-case
                          snake.case  =>  snake-case
                    variable_10_case  =>  variable-10-case
                      variable10Case  =>  variable10-case
                        ɛrgo rE tHis  =>  ɛrgo-r-e-t-his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy-flag-day/12-doc
                             spaces   =>  spaces

Testing function <function allsep_to_space_case at 0x000001F17C262280>:
                           snakeCase  =>  snake case
                          snake_case  =>  snake case
                          snake-case  =>  snake case
                          snake case  =>  snake case
                          snake CASE  =>  snake case
                          snake.case  =>  snake case
                    variable_10_case  =>  variable 10 case
                      variable10Case  =>  variable10 case
                        ɛrgo rE tHis  =>  ɛrgo r e t his
                       hurry-up-joe!  =>  hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my docs/happy flag day/12 doc
                             spaces   =>  spaces

Testing function <function allsep_to_period_case at 0x000001F17C262310>:
                           snakeCase  =>  snake.case
                          snake_case  =>  snake.case
                          snake-case  =>  snake.case
                          snake case  =>  snake.case
                          snake CASE  =>  snake.case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable.10.case
                      variable10Case  =>  variable10.case
                        ɛrgo rE tHis  =>  ɛrgo.r.e.t.his
                       hurry-up-joe!  =>  hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my.docs/happy.flag.day/12.doc
                             spaces   =>  spaces

Testing function <function allsep_to_slash_case at 0x000001F17C2623A0>:
                           snakeCase  =>  snake/case
                          snake_case  =>  snake/case
                          snake-case  =>  snake/case
                          snake case  =>  snake/case
                          snake CASE  =>  snake//case
                          snake.case  =>  snake/case
                    variable_10_case  =>  variable/10/case
                      variable10Case  =>  variable10/case
                        ɛrgo rE tHis  =>  ɛrgo/r/e/t/his
                       hurry-up-joe!  =>  hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c:/my/docs/happy//flag//day/12/doc
                             spaces   =>  spaces

Raku[edit]

The specs are a little vague, but taking a wild stab at it... (May be completely wrong but without any examples of expected output it is hard to judge. This is what I would expect at least...)

my @tests = qww<
snakeCase snake_case variable_10_case variable10Case "ɛrgo rE tHis"
hurry-up-joe! c://my-docs/happy_Flag-Day/12.doc " spaces "
>;
 
 
sub to_snake_case (Str $snake_case_string is copy) {
$snake_case_string.=trim;
return $snake_case_string if $snake_case_string.contains: / \s | '/' /;
$snake_case_string.=subst: / <after <:Ll>> (<:Lu>|<:digit>+) /, {'_' ~ $0.lc}, :g;
$snake_case_string.=subst: / <after <:digit>> (<:Lu>) /, {'_' ~ $0.lc}, :g;
}
 
sub toCamelCase (Str $CamelCaseString is copy) {
$CamelCaseString.=trim;
return $CamelCaseString if $CamelCaseString.contains: / \s | '/' /;
$CamelCaseString.=subst: / ('_') (\w) /, {$1.uc}, :g;
}
 
sub to-kebab-case (Str $kebab-case-string is copy) {
$kebab-case-string.=trim;
return $kebab-case-string if $kebab-case-string.contains: / \s | '/' /;
$kebab-case-string.=subst: / ('_') (\w) /, {'-' ~ $1.lc}, :g;
$kebab-case-string.=subst: / <after <:Ll>> (<:Lu>|<:digit>+) /, {'-' ~ $0.lc}, :g;
$kebab-case-string.=subst: / <after <:digit>> (<:Lu>) /, {'-' ~ $0.lc}, :g;
}
 
say "{' ' x 30}to_snake_case";
printf "%33s ==> %s\n", $_, .&to_snake_case for @tests;
say "\n{' ' x 30}toCamelCase";
printf "%33s ==> %s\n", $_, .&toCamelCase for @tests;
say "\n{' ' x 30}to-kabab-case";
printf "%33s ==> %s\n", $_, .&to-kebab-case for @tests;
Output:
                              to_snake_case
                        snakeCase ==> snake_case
                       snake_case ==> snake_case
                 variable_10_case ==> variable_10_case
                   variable10Case ==> variable_10_case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces

                              toCamelCase
                        snakeCase ==> snakeCase
                       snake_case ==> snakeCase
                 variable_10_case ==> variable10Case
                   variable10Case ==> variable10Case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces

                              to-kabab-case
                        snakeCase ==> snake-case
                       snake_case ==> snake-case
                 variable_10_case ==> variable-10-case
                   variable10Case ==> variable-10-case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces

Wren[edit]

Library: Wren-str
Library: Wren-fmt

Well, I'm not entirely sure what I'm doing here as a result of space and hyphen being treated as equivalent to underscore but, in the case of the 'to snake' conversion:

1. I've retained any hyphens in the result string but replaced spaces with underscores as it says that white space is not permitted as part of the variable name.

2. I've assumed that an underscore should not be added if the previous character was already a separator.

import "./str" for Char
import "/fmt" for Fmt
 
var toCamel = Fn.new { |snake|
snake = snake.trim()
var camel = ""
var underscore = false
for (c in snake) {
if ("_- ".contains(c)) {
underscore = true
} else if (underscore) {
camel = camel + Char.upper(c)
underscore = false
} else {
camel = camel + c
}
}
return camel
}
 
var toSnake = Fn.new { |camel|
camel = camel.trim().replace(" ", "_") // we don't want any spaces in the result
var snake = ""
var first = true
for (c in camel) {
if (first) {
snake = snake + c
first = false
} else if (!first && Char.isUpper(c)) {
if (snake[-1] == "_" || snake[-1] == "-") {
snake = snake + Char.lower(c)
} else {
snake = snake + "_" + Char.lower(c)
}
} else {
snake = snake + c
}
}
return snake
}
 
var tests = [
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "
]
 
System.print(" === to_snake_case ===")
for (camel in tests) {
Fmt.print("$33s -> $s", camel, toSnake.call(camel))
}
 
System.print("\n === toCamelCase ===")
for (snake in tests) {
Fmt.print("$33s -> $s", snake, toCamel.call(snake))
}
Output:
                          === to_snake_case ===
                        snakeCase -> snake_case
                       snake_case -> snake_case
                 variable_10_case -> variable_10_case
                   variable10Case -> variable10_case
                     ɛrgo rE tHis -> ɛrgo_r_e_t_his
                    hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
                         spaces   -> spaces

                         === toCamelCase ===
                        snakeCase -> snakeCase
                       snake_case -> snakeCase
                 variable_10_case -> variable10Case
                   variable10Case -> variable10Case
                     ɛrgo rE tHis -> ɛrgoRETHis
                    hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                         spaces   -> spaces

XPL0[edit]

string  0;              \use zero-terminated strings
char Out(100); \output string (made global for safety)
 
func Trim(Str); \Trim leading and trailing spaces from string
char Str;
int I;
[while Str(0) = $20 do Str:= Str+1; \skip leading spaces
I:= 0; \skip to end of string (+1)
while Str(I) # 0 do I:= I+1;
while I>0 & Str(I-1)=$20 do I:= I-1; \skip back to first non-space
Str(I):= 0; \chop off any trailing spaces
return Str;
];
 
func ToSnake(In); \Convert string to snake_case
char In;
int I, J, C, UL;
[I:= 0; J:= 0; UL:= true; \suppress leading & redundant underlines
repeat C:= In(I); I:= I+1; \get character from input string
if C>=^A & C<=^Z then \convert uppercase to "_" + lowercase
[if not UL then [Out(J):= ^_; J:= J+1];
Out(J):= C+$20; J:= J+1;
UL:= false;
]
else if C=$20 or C=^- then \convert to underlines
[if not UL then [Out(J):= ^_; J:= J+1; UL:= true]
]
else [Out(J):= C; J:= J+1; UL:= C=^_];
until C = 0;
return Out;
];
 
func ToCamel(In); \Convert string to camelCase
char In;
int I, J, C;
[I:= 0; J:= 0;
repeat C:= In(I); I:= I+1;
if C=^_ or C=^- or C=$20 then
[C:= In(I); I:= I+1;
if C>=^a & C<=^z then C:= C-$20;
Out(J):= C; J:= J+1;
]
else [Out(J):= C; J:= J+1];
until C = 0;
return Out;
];
 
int Strings, I;
[Strings:= [
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "\u025brgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", " spaces "];
Text(0, "To snake case:^M^J");
for I:= 0 to 7 do
[Text(0, Strings(I));
Text(0, " -> ");
Text(0, ToSnake(Trim(Strings(I))));
CrLf(0);
];
Text(0, "To camel case:^M^J");
for I:= 0 to 7 do
[Text(0, Strings(I));
Text(0, " -> ");
Text(0, ToCamel(Trim(Strings(I))));
CrLf(0);
];
]
Output:
To snake case:
snakeCase -> snake_case
snake_case -> snake_case
variable_10_case -> variable_10_case
variable10Case -> variable10_case
\u025brgo rE tHis -> \u025brgo_r_e_t_his
hurry-up-joe! -> hurry_up_joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
  spaces   -> spaces
To camel case:
snakeCase -> snakeCase
snake_case -> snakeCase
variable_10_case -> variable10Case
variable10Case -> variable10Case
\u025brgo rE tHis -> \u025brgoRETHis
hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
  spaces -> spaces