Home > database >  Python challenge to convert a string to camelCase
Python challenge to convert a string to camelCase

Time:07-06

I have a python challenge that if given a string with '_' or '-' in between each word such as the_big_red_apple or the-big-red-apple to convert it to camel case. Also if the first word is uppercase keep it as uppercase. This is my code. Im not allowed to use the re library in the challenge however but I didn't know how else to do it.

from re import sub
def to_camel_case(text):
    if text[0].isupper():
      text = sub(r"(_|-) "," ", text).title().replace(" ", "")
    else:
      text = sub(r"(_|-) "," ", text).title().replace(" ", "")
      text = text[0].lower()   text[1:]
      
    return print(text)

CodePudding user response:

Word delimiters can be - dash or _ underscore. Let's simplify, making them all underscores:

    text = text.replace('-', '_')

Now we can break out words:

    words = text.split('_')

With that in hand it's simple to put them back together:

    text = ''.join(map(str.capitalize, words))

or more verbosely, with a generator expression, assign ''.join(word.capitalize() for word in words).

I leave "finesse the 1st character" as an exercise to the reader.


If you RTFM you'll find it contains a wealth of knowledge. https://docs.python.org/3/library/re.html#raw-string-notation

' '

Causes the resulting RE to match 1 or more repetitions of the preceding RE. ab will match ‘a’ followed by any non-zero number of ‘b’s

The effect of is turn both

  • db_rows_read and
  • db__rows_read

into DbRowsRead.

Also,

Raw string notation (r"text") keeps regular expressions sane.

The regex in your question doesn't exactly need a raw string, as it has no crazy punctuation like \ backwhacks. But it's a very good habit to always put a regex in an r-string, Just In Case. You never know when code maintenance will tack on additional elements, and who wants a subtle regex bug on their hands?

CodePudding user response:

You can try it like this :

def to_camel_case(text):
    s = text.replace("-", " ").replace("_", " ")
    s = s.split()
    if len(text) == 0:
        return text
    return s[0]   ''.join(i.capitalize() for i in s[1:])
    
print(to_camel_case('momo_es-es'))

the output of print(to_camel_case('momo_es-es')) is momoEsEs

CodePudding user response:

r"..." refers to Raw String in Python which simply means treating backlash \ as literal instead of escape character.

And (_|-)[ ] is a Regular Expression that match the string containing one or more - or _ characters.

  • (_|-) means matching the string that contains - or _.
  • means matching the above character (- or _) than occur one or more times in the string.

In case you cannot use re library for this solution:

def to_camel_case(text):
    # Since delimiters can have 2 possible answers, let's simplify it to one.
    # In this case, I replace all `_` characters with `-`, to make sure we have only one delimiter.
    text = text.replace("_", "-") # the_big-red_apple => the-big-red-apple
    
    # Next, we should split our text into words in order for us to iterate through and modify it later.
    words = text.split("-") # the-big-red-apple => ["the", "big", "red", "apple"]

    # Now, for each word (except the first word) we have to turn its first character to uppercase.
    for i in range(1, len(words)):
        # `i`start from 1, which means the first word IS NOT INCLUDED in this loop.
        word = words[i]
        
        # word[1:] means the rest of the characters except the first one
        # (e.g. w = "apple" => w[1:] = "pple")
        words[i] = word[0].upper()   word[1:].lower()
        # you can also use Python built-in method for this:
        # words[i] = word.capitalize()

    # After this loop, ["the", "big", "red", "apple"] => ["the", "Big", "Red", "Apple"]

    # Finally, we put the words back together and return it
    # ["the", "Big", "Red", "Apple"] => theBigRedApple
    return "".join(words)


print(to_camel_case("the_big-red_apple"))

CodePudding user response:

Try this:

  • First, replace all the delimiters into a single one, i.e. str.replace('_', '-')
  • Split the string on the str.split('-') standardized delimiter
  • Capitalize each string in list, i.e. str.capitilize()
  • Join the capitalize string with str.join
>>> s = "the_big_red_apple"
>>> s.replace('_', '-').split('-')
['the', 'big', 'red', 'apple']

>>> ''.join(map(str.capitalize, s.replace('_', '-').split('-')))
'TheBigRedApple'

>> ''.join(word.capitalize() for word in s.replace('_', '-').split('-'))
'TheBigRedApple'

If you need to lowercase the first char, then:

>>> camel_mile = lambda x: x[0].lower()   x[1:]
>>> s = 'TheBigRedApple'
>>> camel_mile(s)
'theBigRedApple'

Alternative,

  • First replace all delimiters to space str.replace('_', ' ')
  • Titlecase the string str.title()
  • Remove space from string, i.e. str.replace(' ', '')
>>> s = "the_big_red_apple"
>>> s.replace('_', ' ').title().replace(' ', '')
'TheBigRedApple'

Another alternative,

  • Iterate through the characters and then keep a pointer/note on previous character, i.e. for prev, curr in zip(s, s[1:])
  • check if the previous character is one of your delimiter, if so, uppercase the current character, i.e. curr.upper() if prev in ['-', '_'] else curr
  • skip whitepace characters, i.e. if curr != " "
  • Then add the first character in lowercase, [s[0].lower()]
>>> chars = [s[0].lower()]   [curr.upper() if prev in ['-', '_'] else curr  for prev, curr in zip(s, s[1:])  if curr != " "]
>>> "".join(chars)
'theBigRedApple'

Yet another alternative,

  • Replace/Normalize all delimiters into a single one, s.replace('-', '_')
  • Convert it into a list of chars, list(s.replace('-', '_'))
  • While there is still '_' in the list of chars, keep
    • find the position of the next '_'
    • replacing the character after '_' with its uppercase
    • replacing the '_' with ''
>>> s = 'the_big_red_apple'
>>> s_list = list(s.replace('-', '_'))
>>> while '_' in s_list:
...     where_underscore = s_list.index('_')
...     s_list[where_underscore 1] = s_list[where_underscore 1].upper()
...     s_list[where_underscore] = ""
... 
>>> "".join(s_list)
'theBigRedApple'

or

>>> s = 'the_big_red_apple'
>>> s_list = list(s.replace('-', '_'))
>>> while '_' in s_list:
...     where_underscore = s_list.index('_')
...     s_list[where_underscore:where_underscore 2] = ["", s_list[where_underscore 1].upper()]
... 
>>> "".join(s_list)
'theBigRedApple'

Note: Why do we need to convert the string to list of chars? Cos strings are immutable, 'str' object does not support item assignment


BTW, the regex solution can make use of some group catching, e.g.

>>> import re

>>> s = "the_big_red_apple"

>>> upper_regex_group = lambda x: x.group(1).upper()
>>> re.sub("[_|-](\w)", upper_regex_group, s)
'theBigRedApple'

>>> re.sub("[_|-](\w)", lambda x: x.group(1).upper(), s)
'theBigRedApple'
  • Related