This is a Kata challenge. The function should return a string with spaces between each character. So "Hi there" should equal the the string with spaces between each letter, two spaces between the words. My code actually works in my Python environment, but it is not accepted on Kata.
def spacing(string):
return " ".join(a for a in string).split(string)
A string when iterated over is considered a sequence of characters, so you can simply pass the string to the join method directly:
def spacing(string):
return ' '.join(string)
try
def spacing(string):
return " ".join(string.replace(" ", ""))
this will work if the only whitespaces in string are spaces.
Related
I need to print a string, using this rules:
The first letter should be capital and make all other letters are lowercase. Only the characters a-z A-Z are allowed in the name, any other letters have to be deleted(spaces and tabs are not allowed and use underscores are used instead) and string could not be longer then 80 characters.
It seems to me that it is possible to do it somehow like this:
name = "hello2 sjsjs- skskskSkD"
string = name[0].upper() + name[1:].lower()
lenght = len(string) - 1
answer = ""
for letter in string:
x = letter.isalpha()
if x == False:
answer = string.replace(letter,"")
........
return answer
I think it's better to use a for loop or isalpha () here, but I can't think of a better way to do it. Can someone tell me how to do this?
For one-to-one and one-to-None mappings of characters, you can use the .translate() method of strings. The string module provides lists (strings) of the various types of characters including one for all letters in upper and lowercase (string.ascii_letters) but you could also use your own constant string such as 'abcdef....xyzABC...XYZ'.
import string
def cleanLetters(S):
nonLetters = S.translate(str.maketrans('','',' '+string.ascii_letters))
return S.translate(str.maketrans(' ','_',nonLetters))
Output:
cleanLetters("hello2 sjsjs- skskskSkD")
'hello_sjsjs_skskskSkD'
One method to accomplish this is to use regular expressions (regex) via the built-in re library. This enables the capturing of only the valid characters, and ignoring the rest.
Then, using basic string tools for the replacement and capitalisation, then a slice at the end.
For example:
import re
name = 'hello2 sjsjs- skskskSkD'
trans = str.maketrans({' ': '_', '\t': '_'})
''.join(re.findall('[a-zA-Z\s\t]', name)).translate(trans).capitalize()[:80]
>>> 'Hello_sjsjs_skskskskd'
Strings are immutable, so every time you do string.replace() it needs to iterate over the entire string to find characters to replace, and a new string is created. Instead of doing this, you could simply iterate over the current string and create a new list of characters that are valid. When you're done iterating over the string, use str.join() to join them all.
answer_l = []
for letter in string:
if letter == " " or letter == "\t":
answer_l.append("_") # Replace spaces or tabs with _
elif letter.isalpha():
answer_l.append(letter) # Use alphabet characters as-is
# else do nothing
answer = "".join(answer_l)
With string = 'hello2 sjsjs- skskskSkD', we have answer = 'hello_sjsjs_skskskSkD';
Now you could also write this using a generator expression instead of creating the entire list and then joining it. First, we define a function that returns the letter or "_" for our first two conditions, and an empty string for the else condition
def translate(letter):
if letter == " " or letter == "\t":
return "_"
elif letter.isalpha():
return letter
else:
return ""
Then,
answer = "".join(
translate(letter) for letter in string
)
To enforce the 80-character limit, just take answer[:80]. Because of the way slices work in python, this won't throw an error even when the length of answer is less than 80.
I try to figure out how I can delete certain characters from a string. Unfortunately, it doesn't work. I would appreciate all the help.
def delete_char(string):
string = list(string)
string.remove("\n")
return ''.join(string)
delete_char("I want \n to test \n if you \n work")
How about using replace, instead?
def delete_char(string, target_char, replacement_char=""):
return string.replace(target_char, replacement_char)
print(delete_char("I want \n to test \n if you \n work", "\n"))
You need to re-assign the string value to the removed form. Additionally I would suggest using replace instead of remove in this place, and replacing it with an empty character. Something like this should work:
def delete_char(string):
string = string.replace("\n", "")
return string
You could use str.split and str.join:
>>> ' '.join("I want \n to test \n if you \n work".split())
I want to test if you work
This isn't the same as just removing the newline character but it will ensure only one space between words.
Otherwise just replace the newline with nothing:
>>> "I want \n to test \n if you \n work".replace('\n', '')
I want to test if you work
>>> x = 'abc_cde_fgh'
>>> x.strip('abc_cde')
'fgh'
_fgh is expected.
How to understard this result?
Strip removes any characters it finds from either end from the substring: it doesn't remove a trailing or leading word.
This example demonstrates it nicely:
x.strip('ab_ch')
'de_fg'
Since the characters "a", "b", "c", "h", and "_" are in the remove case, the leading "abc_c" are all removed. The other characters are not removed.
If you would like to remove a leading or trailing word, I would recommend using re or startswith/endswith.
def rstrip_word(str, word):
if str.endswith(word):
return str[:-len(word)]
return str
def lstrip_word(str, word):
if str.startswith(word):
return str[len(word):]
return str
def strip_word(str, word):
return rstrip_word(lstrip_word(str, word), word)
Removing Multiple Words
A very simple implementation (a greedy one) to remove multiple words from a string can be done as follows:
def rstrip_word(str, *words):
for word in words:
if str.endswith(word):
return str[:-len(word)]
return str
def lstrip_word(str, *words):
for word in words:
if str.startswith(word):
return str[len(word):]
return str
def strip_word(str, *words):
return rstrip_word(lstrip_word(str, *words), *words)
Please note this algorithm is greedy, it will find the first possible example and then return: it may not behave as you expect. Finding the maximum length match (although not too tricky) is a bit more involved.
>>> strip_word(x, "abc", "adc_")
'_cde_fgh'
strip() removes characters, not a substring. For example:
x.strip('abcde_')
'fgh'
In the documentation of the strip method "The chars argument is a string specifying the set of characters to be removed." That is why every chars except "fgh" are removed (including the two underscores).
>>> x = 'abc_cde_fgh'
>>> x.strip('abc_cde')
'fgh'
_fgh is expected.
How to understard this result?
Strip removes any characters it finds from either end from the substring: it doesn't remove a trailing or leading word.
This example demonstrates it nicely:
x.strip('ab_ch')
'de_fg'
Since the characters "a", "b", "c", "h", and "_" are in the remove case, the leading "abc_c" are all removed. The other characters are not removed.
If you would like to remove a leading or trailing word, I would recommend using re or startswith/endswith.
def rstrip_word(str, word):
if str.endswith(word):
return str[:-len(word)]
return str
def lstrip_word(str, word):
if str.startswith(word):
return str[len(word):]
return str
def strip_word(str, word):
return rstrip_word(lstrip_word(str, word), word)
Removing Multiple Words
A very simple implementation (a greedy one) to remove multiple words from a string can be done as follows:
def rstrip_word(str, *words):
for word in words:
if str.endswith(word):
return str[:-len(word)]
return str
def lstrip_word(str, *words):
for word in words:
if str.startswith(word):
return str[len(word):]
return str
def strip_word(str, *words):
return rstrip_word(lstrip_word(str, *words), *words)
Please note this algorithm is greedy, it will find the first possible example and then return: it may not behave as you expect. Finding the maximum length match (although not too tricky) is a bit more involved.
>>> strip_word(x, "abc", "adc_")
'_cde_fgh'
strip() removes characters, not a substring. For example:
x.strip('abcde_')
'fgh'
In the documentation of the strip method "The chars argument is a string specifying the set of characters to be removed." That is why every chars except "fgh" are removed (including the two underscores).
can someone please tell me how to fix this? after the last seperator, the code stops and doesn't reach the end of the original string
def split_on_separators(original, separators):
""" (str, str) -> list of str
Return a list of non-empty, non-blank strings from original,
determined by splitting original on any of the separators.
separators is a string of single-character separators.
>>> split_on_separators("Hooray! Finally, we're done.", "!,")
['Hooray', ' Finally', " we're done."]
"""
result = []
newstring=''
for char in original:
if char in separators:
result.append(newstring)
newstring = ""
else:
newstring += char
return result
import re
def split_on_separators(original, separators):
return re.split("[" + separators + "]", original)
OK, this isn't perfect because certain characters cannot appear in separators because it's used to build a regex, but it works for many cases including the one in the question. A more robust way would be to simply use re.split instead of this function in the first place.
You need to append newstring to result once the loop is completed / before you return. Since there are no separators after the last string it will otherwise never get added since only encountering a separator causes appendage to the list.
The code only puts a part of the input string in result when it hits a separator. Since there is no separator at the end of your sample input, the "we're done" in newstring is not appended to result. To fix this you would have add an if statement after the for to see if there was something in newstring, and then append it if necessary.