How to replace part of string with a character - python

I'm trying to creating a code that prints till 'n' and replaces the rest of the characters with "*".
This is my code so far"
def replace(s,n):
return s.replace(s[n:], "*")
However it outputs
replace("hello", 2)
'he*'
it should be 'he***'

You should multiply "*" by the number of characters you want to replace. In addition, you should add (len(s)-n)*"*" after s[n:] instead of replacing (as the same set of characters may appear in several places in the string). You may do that as follows:
def replace(s,n):
return s[:n]+(len(s)-n)*"*"
replace('hello', 2)
This prints 'he***'

There are two fundamental issues. First, s.replace will replace the entire first argument with the second. And perhaps even more important, it replaces it anywhere it finds it on the string. So, consider the following example:
>>> def replace(s,n):
... return s.replace(s[n:], "*")
...
>>> replace('lalahahalala', 8)
'*haha*'
>>>
Instead, you should take a different approach, iterate the string, returning the character in that string if the index is < n, else, return '*':
>>> def replace(s, n):
... return ''.join(c if i < n else '*' for i,c in enumerate(s))
...
>>> replace("hello", 2)
'he***'
>>> replace('lalahahalala', 8)
'lalahaha****'
Here is a version of the above using a for-loop instead of a generator expression:
>>> def replace(s, n):
... char_list = []
... for i, c in enumerate(s):
... if i < n:
... char_list.append(c)
... else:
... char_list.append('*')
... return ''.join(char_list)
...
>>> replace('hello', 2)
'he***'
>>> replace('lalahahalala', 8)
'lalahaha****'
>>>

The replace approach is fundamentally flawed, because replace looks for a substring to replace anywhere in the source string, it's not for replacing characters at some position. Even with the "fixed" version by #MiriamFarber (now he edited it, look at the revision history) you'd get erroneous output like
replace("chachacha", 6) # returns *********
What you want is to truncate the string at the requested position, and append to it a string of as many asterisks as the characters you removed.
def replace(s, n):
return s[:n] + '*'*(len(s)-n)

You can slice s until n position and then concatenate the rest of the string using * operator. You don't need to use replace method:
def replace(s,n):
return s[:n] + (len(s)-n)*'*'
The output is:
replace('hello', 2)
'he***'

Related

Replace substring of given indices range

I am new in Python programming. I am stuck at one point. Let's say I have string "hello-world". I want to replace all the characters of this string with "*" except first & last. so the result will be "h***-****d".
One way to do this as below:
In [1]: s = "hello-world"
In [2]: s[0] + "*"*(len(s)-2) + s[-1]
Out[2]: 'h*********d'
If I want to replace all characters with "*" except first & last 2 characters
In [3]: s[:2] + "*"*(len(s)-4) + s[-2:]
Out[3]: 'he*******ld'
Is there any pretty way to handle these type of problems. Any help would be appreciated. Thanks.
I think what you want to do is this:
def obscure(string, n):
characters = list(string)
characters[n:-n] = '*' * len(characters[n:-n])
obscured = ''.join(characters)
return obscured
Turn the string into a list of characters. Replace the ones you want to obscure. Then join the list back into a string.
You can use str.join (and the string module to check against letters):
s[0] + ''.join(['*' if i in string.ascii_letters else i
for i in s[1:-1]]) + s[-1]
Since you said you wanted h****-****d where the hyphen isn't replaced, you would need to test whether the characters are letters or not. You could change string.ascii_letters to:
chars = 'abcdefghijklmnopqrstuvwxyz'
chars = chars + chars.upper() + '0123456789' # + 'some_other_chars'
...if you want to include other characters like numbers or punctuation. Or you can write out the letters you want to replace manually.
You may also want to perform a check to see whether the string is 3 characters or more so that no errors are raised.
You could define a function to not repeat yourself:
def replace(s, n):
if len(s) > n*2:
return s[:n] + '*'*(len(s)-n*2) + s[-n:]
return s
print(replace('hello-world', 1)) # h*********d
print(replace('hello-world', 2)) # he*******ld
print(replace('hello', 2)) # he*lo
print(replace('hello', 3)) # hello
You can also use some kind of string formatting instead of concatenation (which should be more efficient), e.g. f-strings available in 3.6+:
def replace(s, n):
if len(s) > n*2:
return f"{ s[:n] }{ '*'*(len(s)-n*2) }{ s[-n:] }"
return s
You can try this.
s="hello-world"
for i in s[1:-1]:
if i.isalpha():
s=s.replace(i,"*")

Replace input strings and integers

I need to write a function that takes a string (str), and two other strings (call it replace1 and replace2), and an integer (n). The function shall return a new string, where all the string inputs from replace1 in the first string (str) and replace the new string with replace1 depending on where you want the new input. I am not supposed to use built-in functions, but I can use lens (we can suppose that replace1 has the length 1). Example ( call it replaceChoice):
>>> replaceChoice(“Mississippi”, “s”, “l”, 2)
'Mislissippi'
I hope that I explained it well. Here is my attempt:
def replaceChoice(str1, replace1,n):
newString=""
for x in str:
if x=="str1":
newString=newString+replace
else:
newString=newString+x
return newString
I assume from your question that you want to replace the nth occurrence of r1 with r2.
Is this what you want?
>>> def replaceChoice(str1, r1, r2, n):
... new_str = ""
... replaced = False
... for i in str1:
... if i==r1:
... n-=1
... if n==0 and not replaced:
... replaced = True
... new_str+=r2
... else:
... new_str+=i
... return new_str
...
>>> replaceChoice("Mississippi", "s", "l", 2)
'Mislissippi'

Python - making a function that would add "-" between letters

I'm trying to make a function, f(x), that would add a "-" between each letter:
For example:
f("James")
should output as:
J-a-m-e-s-
I would love it if you could use simple python functions as I am new to programming. Thanks in advance. Also, please use the "for" function because it is what I'm trying to learn.
Edit:
yes, I do want the "-" after the "s".
Can I try like this:
>>> def f(n):
... return '-'.join(n)
...
>>> f('james')
'j-a-m-e-s'
>>>
Not really sure if you require the last 'hyphen'.
Edit:
Even if you want suffixed '-', then can do like
def f(n):
return '-'.join(n) + '-'
As being learner, it is important to understand for your that "better to concat more than two strings in python" would be using str.join(iterable), whereas + operator is fine to append one string with another.
Please read following posts to explore further:
Any reason not to use + to concatenate two strings?
which is better to concat string in python?
How slow is Python's string concatenation vs. str.join?
Also, please use the "for" function because it is what I'm trying to learn
>>> def f(s):
m = s[0]
for i in s[1:]:
m += '-' + i
return m
>>> f("James")
'J-a-m-e-s'
m = s[0] character at the index 0 is assigned to the variable m
for i in s[1:]: iterate from the second character and
m += '-' + i append - + char to the variable m
Finally return the value of variable m
If you want - at the last then you could do like this.
>>> def f(s):
m = ""
for i in s:
m += i + '-'
return m
>>> f("James")
'J-a-m-e-s-'
text_list = [c+"-" for c in text]
text_strung = "".join(text_list)
As a function, takes a string as input.
def dashify(input):
output = ""
for ch in input:
output = output + ch + "-"
return output
Given you asked for a solution that uses for and a final -, simply iterate over the message and add the character and '-' to an intermediate list, then join it up. This avoids the use of string concatenations:
>>> def f(message)
l = []
for c in message:
l.append(c)
l.append('-')
return "".join(l)
>>> print(f('James'))
J-a-m-e-s-
I'm sorry, but I just have to take Alexander Ravikovich's answer a step further:
f = lambda text: "".join([c+"-" for c in text])
print(f('James')) # J-a-m-e-s-
It is never too early to learn about list comprehension.
"".join(a_list) is self-explanatory: glueing elements of a list together with a string (empty string in this example).
lambda... well that's just a way to define a function in a line. Think
square = lambda x: x**2
square(2) # returns 4
square(3) # returns 9
Python is fun, it's not {enter-a-boring-programming-language-here}.

How to return (x) number of characters in a given string?

I've been at this for a while now, and I've gotten so close.
I've had two problems to complete for an assignment. The first one I finished. It's supposed to return the first three indices of the given string, and if the string is less than 3 letters, it returns nothing. It looks like this:
The second one is similar, but a little more involved. The problem is:
Hopefully that explains my issue. I can't figure out how to get the inputted number to correspond to the number of indices I'm trying to print. In the first problem, it was simple, because it was always just the first three indices that were used. Now, it's (n) number of indices.
Any help is much appreciated (I'm using Python 3.4.2)
Strings support sub-stringing in Python.
def returnN(string, length):
return string[:length] if len(string) >= length else ''
In action:
>>> returnN('hello', 2)
'he'
>>> returnN('hello', 5)
'hello'
>>> returnN('BYE', 1)
'B'
>>> returnN('BYE', 10)
''
Use len and slice method of string method like:
def returnN(string, length):
length_string = len(string)
if length > length_string:
return ''
return string[0:length]
print(returnN('hello', 5))
print(returnN('hello', 2))
print(returnN('Nye', 1))
print(returnN('OKOK', 10))
or simple way:
def returnN_S(string, length):
return string[: length] if length <= len(string) else ''
print(returnN_S('hello', 5))
print(returnN_S('hello', 2))
print(returnN_S('Nye', 1))
print(returnN_S('OKOK', 10))
or one line way:
returnN_H = lambda string, length: string[: length] if length <= len(string) else ''
print(returnN_H('hello', 5))
print(returnN_H('hello', 2))
print(returnN_H('Nye', 1))
print(returnN_H('OKOK', 10))
Hope helps.
Unicode strings in Python are immutable Unicode codepoint sequences.
Unicode codepoint is just a number from 0 to sys.maxunicode e.g., Nº128516: 😄('\U0001f604').
A substring/slice of a Unicode string s such as s[:2] returns a new Unicode string that contains 2 Unicode codepoints.
len(s) returns the number of Unicode codepoints in the string s.
An empty string could be represented using '' string literal in Python source code.
To return a given number of user-perceived characters from a string or an empty string if the text size is too small, you could use \X regular expression (it matches an eXtended grapheme cluster):
#!/usr/bin/env python3
import regex # $ pip install regex
def returnN(text, n):
chars = regex.findall(r'\X', text)
return ''.join(chars[:n]) if len(chars) >= n else ''
text = 'a\u0300 biento\u0302t'
print(text) # -> à bientôt
print(returnN(text, 4)) # -> à bi
A single user-perceived character such as à can span several Unicode codepoints such as U+0061, U+0300.
The term character is ambiguous. It can mean a byte, Unicode codepoint, grapheme cluster in different circumstances.
input_string = "hello"
def returnN(string, n):
return string[:n]
output = returnN(input_string, 3)
that's all

Python: loop over consecutive characters?

In Python (specifically Python 3.0 but I don't think it matters), how do I easily write a loop over a sequence of characters having consecutive character codes? I want to do something like this pseudocode:
for Ch from 'a' to 'z' inclusive: #
f(Ch)
Example: how about a nice "pythonic" version of the following?
def Pangram(Str):
''' Returns True if Str contains the whole alphabet, else False '''
for Ch from 'a' to 'z' inclusive: #
M[Ch] = False
for J in range(len(Str)):
Ch = lower(Str[J])
if 'a' <= Ch <= 'z':
M[Ch] = True
return reduce(and, M['a'] to M['z'] inclusive) #
The lines marked # are pseudocode. Of course reduce() is real Python!
Dear wizards (specially old, gray-bearded wizards), perhaps you can tell that my favorite language used to be Pascal.
You have a constant in the string module called ascii_lowercase, try that out:
>>> from string import ascii_lowercase
Then you can iterate over the characters in that string.
>>> for i in ascii_lowercase :
... f(i)
For your pangram question, there is a very simple way to find out if a string contains all the letters of the alphabet. Using ascii_lowercase as before,
>>> def pangram(str) :
... return set(ascii_lowercase).issubset(set(str))
Iterating a constant with all the characters you need is very Pythonic. However if you don't want to import anything and are only working in Unicode, use the built-ins ord() and its inverse chr().
for code in range(ord('a'), ord('z') + 1):
print chr(code)
You've got to leave the Pascal-isms behind and learn Python with a fresh perspective.
>>> ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> def pangram( source ):
return all(c in source for c in ascii_lowercase)
>>> pangram('hi mom')
False
>>> pangram(ascii_lowercase)
True
By limiting yourself to what Pascal offered, you're missing the things Python offers.
And... try to avoid reduce. It often leads to terrible performance problems.
Edit. Here's another formulation; this one implements set intersection.
>>> def pangram( source ):
>>> notused= [ c for c in ascii_lowercase if c not in source ]
>>> return len(notused) == 0
This one gives you a piece of diagnostic information for determining what letters are missing from a candidate pangram.
A more abstract answer would be something like:
>>> x="asdf"
>>> for i in range(len(x)):
... print x[i]
Hacky
method_1 = [chr(x) for x in range(ord('a'), ord('z')+1)]
print(method_1)
Neat
# this is the recommended method generally
from string import ascii_lowercase
method_2 = [x for x in ascii_lowercase]
print(method_2)
I would write a function similar to Python's range
def alpha_range(*args):
if len(args) == 1:
start, end, step = ord('a'), ord(args[0]), 1
elif len(args) == 2:
start, end, step = ord(args[0]), ord(args[1]), 1
else:
start, end, step = ord(args[0]), ord(args[1]), args[2]
return (chr(i) for i in xrange(start, end, step))

Categories

Resources