This is my code trying to convert a sentence to camel case whenever a '-' or '_' appears.
def to_camel_case(text):
for i in text:
if text[0].isupper():
text[0] = text[0].upper()
elif i == '_' or i == '-':
text[i] = text[i].upper()
return text
On executing the code it says the mentioned error. I know the error is somewhere in the line text[i] = text[i].upper() but I can't figure it out. Thanks.
IIUC you can use string.title having replaced both - or _ to spaces with re.sub:
import re
s = "hello_world"
re.sub('_|-',' ',s).title()
# 'Hello World'
A Non-Regex / Crude-Logic(:D) version:
def to_camel_case(text):
pos_list = [x+1 for x,c in enumerate(text) if ((c == '_' or c == '-') and (x!=len(text)))]
new_text_list = []
for i, c in enumerate(text):
if (c == '-' or c == '_'):
continue
if i in pos_list:
new_text_list.append(c.upper())
else:
new_text_list.append(c)
return "".join(x for x in new_text_list)
print to_camel_case("hey_there")
print to_camel_case("-In_this_World_")
print to_camel_case("hello_world")
Output:
heyThere
InThisWorld
helloWorld
Related
I'm trying to create a function that -given a string- will return the count of non-allowed characters ('error_char'), like so: 'total count of not-allowed / total length of string'.
So far I've tried:
def allowed_characters(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
counter = 0
for i in s:
if i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
elif i in error_char:
counter += 1
result = str(sum(counter)) + '/' + str(len(s))
return result
but all I get is '0/56' where I'm expecting '22/56' since m,x,y,z are 'not allowed' and m repeats 19 times
allowed_characters('aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbmmmmmmmmmmmmmmmmmmmxyz')
'0/56'
Then I've tried:
def allowed_characters(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
counter = 0
for i in s:
if i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
elif i in error_char:
import regex as re
rgx_pattern = re.compile([error_char])
count_e = rgx_pattern.findall(error_char, s)
p_error = sum([count_e.count(i) for i in error_char])
result = str(p_error) + '/' + str(len(s))
But I get the same result...
I've also tried these other ways, but keep getting the same:
def allowed_characters1(s):
s = s.lower()
correct_char = 'abcdef'
for i in s:
if i not in correct_char:
counter = sum([s.count(i) for i in s])
p_error = str(counter) + '/' + str(len(s))
return p_error
elif i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
and...
def allowed_characters2(s):
s = s.lower()
correct_char = 'abcdef'
for i in s:
if i not in correct_char:
counter = sum(s.count(i))
p_error = str(counter) + '/' + str(len(s))
return p_error
elif i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
I've even tried changing the logic and iterating over 'correct/error_char' instead, but nothing seems to work... I keep getting the same result over and over. It looks as though the loop stops right after first character or doesn't run the 'elif' part?
Whenever it comes to do quicker counting - it's always good to think about Counter You can try to simplify your code like this:
Notes - please don't change your Problem Description during the middle of people's answering posts. That make it very hard to keep in-sync.
There is still room to improve it though.
from collections import Counter
def allowed_char(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
ok_counts = Counter(s)
print(f' allowed: {ok_counts} ')
correct_count = sum(count for c, count in ok_counts.items() if c in correct_char)
error_count = sum(count for c, count in ok_counts.items() if c in error_char)
#return sum(not_ok.values()) / total
return correct_count, error_count # print both
s =('aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbmmmmmmmmmmmmmmmmmmmxyz')
print(allowed_char(s)) # (34, 22)
print(allowed_char('abdmmmmxyz')) # (3, 7)
Alternatively, you really want to use for-loop and learn to process the string of characters, you could try this:
def loop_count(s):
s = s.lower()
correct_count = error_count = 0
for c in s:
if c in correct_char:
correct_count += 1
else:
error_count += 1
return correct_count, error_count
I would use a regex replacement trick here using len():
def allowed_characters(s):
return len(s) - len(re.sub(r'[^ghijklmnopqrstuvwxyz]+', '', s))
The above returns the length of the input string minus the length of the input with all allowed characters removed (alternatively minus the length of the string with only non allowed characters).
I make a function to input string and return with head and tail with two indexes without space and punctuation. but it's return only "empty string"
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String : ")
result = hello(word)
print("Result: ",result)
I expect when I input "hello world!", and the actual output is "held"
or "Hi!" = "HiHi".
The problem is simply incorrect indentation:
import string
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2:
return "empty string"
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String: ")
result = hello(word)
print("Result: ", result)
Indentation is everything in Python!
> python3 test.py
Input String: hello world!
Result: held
>
However, if the input is long, this is the wrong way to go about the problem. We test a lot of characters we'll never use against the whitespace and punctuation lists. Instead we should grab the first two valid characters from either end of the list and ignore the middle. Something like:
def hello(word):
unwanted = string.whitespace + string.punctuation
str_start = ""
for letter in word:
if letter not in unwanted:
str_start += letter
if len(str_start) == 2:
break
if len(str_start) < 2:
return "empty string"
str_end = ""
for idx in range(len(word) - 1, -1, -1):
if word[idx] not in unwanted:
str_end = word[idx] + str_end
if len(str_end) == 2:
break
return str_start + str_end
EXAMPLE
> python3 test2.py
Input String: telecommunications!
Result: tens
>
The letters 'lecommunicatio' were never tested as they had no effect on the eventual outcome.
You miss-indented the last if block:
import string
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String : ")
result = hello(word)
print("Result: ",result)
Example output:
Input String : Hello World!
Result: Held
Your issue is that you return after the first iteration through the work, no matter what.
Move the return nogic after the logic:
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
The problem is indentation as everyone says, after correcting which it works. I would do it more pythonically as:
def hello(word):
w = ''.join([x for x in word if x not in string.whitespace and x not in string.punctuation])
return w[:2] + w[-2:] if len(w) > 1 else 'empty string'
Usage:
>>> hello('hello world!')
held
Test Cases
Input: abbbaaccada
Output: ccada
Input: bbccdddcb
Output: (Empty string)
str = input("Enter string: ")
def my_string(string):
if not string:
return ""
if len(string) == 1:
return string
if string[0] == string[1] == string[2]:
return my_string(string[3:])
return string[0] + my_string(string[1:])
print (my_string(str))
I am new to python. and I am trying to remove characters with 3 or more consecutive appearance in a string. In this I could only able to get output of only 1 iteration. e.g. i/p- hhhelllo o/p-eo but for i/p- abbbaaccada o/p is aaaccada but it should be ccada.. please help..
I have done this till 3 repetition but how to generalize it for more than 3 repetition.??
Your problem presents the opportunity to show how else in for loops can be useful. Take a look:
def remover(my_str):
temp = set(my_str)
while True:
for c in temp:
if 3*c in my_str:
my_str = my_str.replace(3*c, '')
break
else:
break
return my_str
test1 = 'abbbaaccada'
print(remover(test1)) # -> ccada
test2 = 'i/p- hhhelllo'
print(remover(test2)) # -> i/p- eo
If you insist on having recursive calls, you can modify the above as follows:
def remover(my_str):
temp = set(my_str)
new_str = my_str
for c in temp:
if 3*c in new_str:
new_str = new_str.replace(3*c, '')
if my_str == new_str:
return new_str
else:
return remover(new_str)
I have added a solution which will work for 3 or more repetition as the above solution didn't work for me. It is a recursive solution.
import re
def format_string(u_str):
f_str = remove_string(u_str)
if f_str == u_str:
return f_str
else:
return format_string(f_str)
def remove_string(u_str):
index = 0 # This will maintain the index while traversing the entire string
while index < len(u_str):
r = re.search(u_str[index]*4 + '*', u_str)
if r:
start, end = r.span() # start and end index of substring matching 3 or more repetition
u_str = u_str[:start] + u_str[end:] # removing the found substring
index = end
else:
index += 1
return u_str
test1 = 'abbbaaccada'
print('output:' + format_string(test1))
test2 = 'bbccdddcb'
print('output:' + format_string(test2))
I have a string like '....(((...((...' for which I have to generate another string 'ss(4)h5(3)ss(3)h2(2)ss(3)'.
'.' corresponds to 'ss' and the number of continous '.' is in the bracket.
'(' corresponds to 'h5' and the number of continuos '(' is in the bracket.
Currently I'm able to get the output 'ss(4)h5(3)ss(3)' and my code ignores the last two character sequences.
This is what I have done so far
def main():
stringInput = raw_input("Enter the string:")
ssCount = 0
h5Count = 0
finalString = ""
ssString = ""
h5String = ""
ssCont = True
h5Cont = True
for i in range(0, len(stringInput), 1):
if stringInput[i] == ".":
h5Cont = False
if ssCont:
ssCount = ssCount + 1
ssString = "ss(" + str(ssCount) + ")"
ssCont = True
else:
finalString = finalString + ssString
ssCont = True
ssCount = 1
elif stringInput[i] == "(":
ssCont = False
if h5Cont:
h5Count = h5Count + 1
h5String = "h5(" + str(h5Count) + ")"
h5Cont = True
else:
finalString = finalString + h5String
h5Cont = True
h5Count = 1
print finalString
main()
How to modify the code to get the desired output?
I don’t know about modifying your existing code, but to me this can be done very succinctly and pythonically using itertools.groupby. Note that I’m not sure if the 'h2' in your expected output is a typo or if it should be 'h5', which I’m assuming.
from itertools import chain, groupby
string = '....(((...((...'
def character_count(S, labels): # this allows you to customize the labels you want to use
for K, G in groupby(S):
yield labels[K], '(', str(sum(1 for c in G)), ')' # sum() counts the number of items in the iterator G
output = ''.join(chain.from_iterable(character_count(string, {'.': 'ss', '(': 'h5'}))) # joins the components into a single string
print(output)
# >>> ss(4)h5(3)ss(3)h5(2)ss(3)
#Kelvin 's answer is great, however if you want to define a function yourself, you could do it like this:
def h5ss(x):
names = {".": "ss", "(": "h5"}
count = 0
current = None
out = ""
for i in x:
if i == current:
count += 1
else:
if current is not None:
out += "{}({})".format(names[current], count)
count = 1
current = i
if current is not None:
out += "{}({})".format(names[current], count)
return out
I need a python function that can do the following:
Given an input of 't' and 'tattle', it should return a list like so:
['Tattle','taTtle','tatTle']
Or with 'z' and 'zzzzz':
['Zzzzz','zZzzz','zzZzz','zzzZz','zzzzZ']
I coded the following, but it does not work with the second example because the current function checks to see if the basestr matches what is already in the resulting list, R, and can pick up false positives due to words with multiple basestr's already in the word. Anyone have any advice?
def all_variants(wrapletter,word):
L,R,WLU,basestr=list(word),[],wrapletter.upper(),''
if L.count(wrapletter)==1:
for char in L:
if wrapletter==char:
basestr=basestr+WLU
else:
basestr=basestr+char
R.append(basestr)
return(R)
else:
for i in range(L.count(wrapletter)):
basestr=''
if i==0 and L[0]==wrapletter:
basestr=WLU
for char in range(1,len(L)):
basestr=basestr+L[char]
R.append(basestr)
else:
for char in L:
if wrapletter==char:
if WLU in basestr:
basestr=basestr+char
elif basestr in str(R):
basestr=basestr+char
else:
basestr=basestr+WLU
else:
basestr=basestr+char
R.append(basestr)
R.remove(R[0])
return(R)
It's not elegant, but maybe it's what you need?
target = "daaddaad"
def capitalize(target_letter, word):
return [word[:i] + word[i].upper() + word[i + 1:]
for i in xrange(len(word)) if word[i] == target_letter]
print capitalize("d", target)
Outputs:
['Daaddaad', 'daaDdaad', 'daadDaad', 'daaddaaD']
inp = 't'
word = 'tattle'
inds = (i for i,ele in enumerate(word) if ele == inp)
print([word[:i]+word[i].upper()+word[i+1:] for i in inds])
['Tattle', 'taTtle', 'tatTle']
Try this. I iterate through each letter, shift it to uppercase, and sandwich it with the other parts of the original string.
def all_variants(wrapletter, word):
variants = []
for i, letter in enumerate(word):
if letter == wrapletter:
variants.append(word[:i] + letter.upper() + word[i+1:])
return variants
print all_variants('z', 'zzzzz')
print all_variants('t', 'tattle')
def all_variants(wrapletter, word):
list = []
for i in range(len(word)):
if(word[i]==wrapletter):
start = word[0:i].lower()
str = word[i].upper()
end = word[i+1::].lower()
list.append(start+str+end)
return list
These returned when I ran this function:
>>>all_variants("t", "tattle")
['Tattle', 'taTtle', 'tatTle']
>>>all_variants("z", "zzzzz")
['Zzzzz', 'zZzzz', 'zzZzz', 'zzzZz', 'zzzzZ']