Camel Case

August 29, 2017

Some programmers write variable names in camelCase, each word starting with a capital letter, while other programmers separate words with underscores like_this.

Your task is to write programs that convert between the two forms. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2

8 Responses to “Camel Case”

  1. This gives a slightly different answer (when the first character is upper case as it doesn’t prefix it with an underscore…;

    sub from_cc {
      return join '_', map { $_ } split /(?=[A-Z])/, shift;
    }
    sub to_cc {
      my $t = join '', map { ucfirst lc $_ } split /_/, shift;
      substr $t,0,1,lc substr $t,0,1;
      return $t;
    }
    
  2. Paul said

    In Python. Probably the regex split can be improved to handle multiple capitals, but I did not manage yet.

    def split_on_case(txt):
        return regex.split("(?V1)(?<=[a-z])(?=[A-Z])", txt)
    
    def split_on_case(txt):
        S, last = [], ""
        G = ["".join(g) for k, g in groupby(txt, str.isupper)]
        for g in G:
            if str.isupper(g):
                if g == G[-1]:
                    S.append(g)
                elif len(g) > 1:
                    S.append(g[:-1])
                    last = g[-1]
                else:
                    last = g
            else:
                S.append("".join((last, g)))
        return S
    
    def camel_underscore(txt):
        elts = [w.lower() for w  in split_on_case(txt)]
        return "_".join(elts)
    
    def underscore_camel(txt):
        elts = [w[0].upper() + w[1:] for w in txt.split("_")]
        return "".join(elts)
    
    
    print(camel_underscore("CamelCase"))
    print(underscore_camel("def_with_underscores"))
    print(camel_underscore("getHTPPClient"))
    print(camel_underscore("getHTPP"))
    print(underscore_camel("get_HTTP_client"))
    
    """
    with lengthy split method
    camel_case
    DefWithUnderscores
    get_htpp_client
    get_htpp
    GetHTTPClient
    
    with regex
    camel_case
    DefWithUnderscores
    get_htppclient
    get_htpp
    GetHTTPClient
    """
    
  3. Zack said

    Why would anyone want to convert to the underscore format? Although this may be a very interesting exercise programmatically, I find its use case quite limited.

  4. programmingpraxis said

    @Zack: Underscore case is the convention in some languages, including Oracle SQL and PL/SQL which I use every day in my regular job.

    On Tue, Aug 29, 2017 at 9:08 AM, Programming Praxis wrote:

    >

  5. chaw said

    (import (scheme base)
            (srfi 1)
            (scheme char)
            (scheme write))
    
    ;;; Naive versions, based on literal interpretation
    
    (define (camel->snake str)
      (list->string (reverse (fold (lambda (c lst)
                                     (if (char-upper-case? c)
                                         (cons (char-downcase c) (cons #\_ lst))
                                         (cons c lst)))
                                   '()
                                   (string->list str)))))
    
    (camel->snake "fooBarBazItIs")
    
    (define (snake->camel str)
      (list->string (reverse (fold (lambda (c lst)
                                     (if (and (pair? lst)
                                              (char=? #\_ (car lst)))
                                         (cons (char-upcase c) (cdr lst))
                                         (cons c lst)))
                                   '()
                                   (string->list str)))))
    
    (snake->camel (camel->snake "fooBarBazItIs"))
    
    ;;; A different version of camel->snake.
    
    ;; We will use the rule that an uppercase character X is treated as
    ;; special (i.e., it is subjected to the rewriting X -> _x) iff there
    ;; is a lowercase character immediately to the left or (inclusive)
    ;; right of X.
    (define (camel-hump? str idx)
      (and (char-upper-case? (string-ref str idx))
           (or (and (> idx 0)
                    (char-lower-case? (string-ref str (- idx 1))))
               (and (< idx (- (string-length str) 1))
                    (char-lower-case? (string-ref str (+ idx 1)))))))
    
    (define (show-humps str)
      (map (lambda (i)
             (cons (string-ref str i)
                   (camel-hump? str i)))
           (iota (string-length str))))
    
    (define (camel->snake/grouping str)
      (apply string-append
             (list-tabulate (string-length str)
                            (lambda (i)
                              (if (camel-hump? str i)
                                  (string #\_ (string-ref str i))
                                  (string (string-ref str i)))))))
    
    (map camel->snake/grouping
         '("HTTPClient" "getHTTP" "XMLServer" "XMLHTTPServer"))
    
    (map snake->camel
         (map camel->snake/grouping
              '("HTTPClient" "getHTTP" "XMLServer" "XMLHTTPServer")))
    
    ;;;
    

  6. Paul said

    A shorter version of the split function.

    def split_on_case(txt):
        program = re.compile("[A-Z]?[a-z]+")
        splits = set([0, len(txt)])
        for m in program.finditer(txt):
            splits.update(m.span())
        return [txt[b:e] for b, e in pairwise(sorted(splits))]
    
  7. V said

    Solution for ASCII characters in Ruby.

    
    def camel_to_snake(camel_string)
      camel_string.gsub(/[a-z][A-Z]/) { |x| x.chars.join('_').downcase }
    end
    
    def snake_to_camel(snake_string)
      snake_string.gsub(/_[a-z]/) { |x| x.chars.last.upcase }
    end
    
    

    The test…

    
    def test(fn, input, target)
      output = self.send(fn, input)
      puts "%-17s : %-17s %s" % [input, output, (target == output ? '✅' : '❌')]
    end
    
    puts "Snake to Camel case"
    test :camel_to_snake, 'one',             'one'             
    test :camel_to_snake, 'camelCase',       'camel_case'      
    test :camel_to_snake, 'likeThis',        'like_this'       
    test :camel_to_snake, 'doTheEvolution',  'do_the_evolution'
    
    puts
    puts "Camel to Snake case"
    test :snake_to_camel, 'one',             'one'             
    test :snake_to_camel, 'camel_case',      'camelCase'      
    test :snake_to_camel, 'like_this',       'likeThis'       
    test :snake_to_camel, 'do_the_evolution', 'doTheEvolution'
      
    

    Outputs:

    
    Snake to Camel case
    one               : one               ✅
    camelCase         : camel_case        ✅
    likeThis          : like_this         ✅
    doTheEvolution    : do_the_evolution  ✅
    
    Camel to Snake case
    one               : one               ✅
    camel_case        : camelCase         ✅
    like_this         : likeThis          ✅
    do_the_evolution  : doTheEvolution    ✅
    
    
  8. V said

    Solution for ASCII characters in Ruby. (Posting again without Emojis)

    
    def camel_to_snake(camel_string)
      camel_string.gsub(/[a-z][A-Z]/) { |x| x.chars.join('_').downcase }
    end
    
    def snake_to_camel(snake_string)
      snake_string.gsub(/_[a-z]/) { |x| x.chars.last.upcase }
    end
    
    

    The test…

    
    def test(fn, input, target)
      output = self.send(fn, input)
      puts "%-17s : %-17s %s" % [input, output, (target == output ? 'OK' : 'FAIL')]
    end
    
    puts "Snake to Camel case"
    test :camel_to_snake, 'one',             'one'             
    test :camel_to_snake, 'camelCase',       'camel_case'      
    test :camel_to_snake, 'likeThis',        'like_this'       
    test :camel_to_snake, 'doTheEvolution',  'do_the_evolution'
    
    puts
    puts "Camel to Snake case"
    test :snake_to_camel, 'one',             'one'             
    test :snake_to_camel, 'camel_case',      'camelCase'      
    test :snake_to_camel, 'like_this',       'likeThis'       
    test :snake_to_camel, 'do_the_evolution', 'doTheEvolution'
      
    

    Outputs:

    
    Snake to Camel case
    one               : one               OK
    camelCase         : camel_case        OK
    likeThis          : like_this         OK
    doTheEvolution    : do_the_evolution  OK
    
    Camel to Snake case
    one               : one               OK
    camel_case        : camelCase         OK
    like_this         : likeThis          OK
    do_the_evolution  : doTheEvolution    OK
    
    

    @programmingpraxis fell free to delete my previous post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: