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
anddb__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_
.-
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''
- find the position of the next
>>> 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'