Could anybody explain inside functioning of .replace method in Python? - python-3.x

I want to solve a problem which takes two inputs, 1st is a string and 2nd is it's substring. Then i have to remove all occurences of the substring in the string and return the remaining part of string.
Without using replace method.
Now if I know the length of substring, it's doable, but what if the length is unknown?
Thanks
Here's my answer, it fails when there are multiple occurrences of substring in the string. Now it works correctly.
inputS=input('string?')
inputSub=input('substring?')
s=list(inputS)
sub=list(inputSub)
print(sub)
z=len(s)-len(sub)+1
y=len(sub)
def remove_sub():
li=[] #index at which substring is present
for x in range(z):
if s[x]==sub[0]:
if y==1:
li.append(x)
continue
for temp in range(1,y):
if s[x+temp]==sub[temp]:
temp+=1
if temp==y:
li.append(x)
else:
print(x)
else:
continue
return(li)
li=remove_sub()
print(li)
temp2=0
for i in range(len(li)): #removing substring
del s[li[i]+temp2:(li[i]+y+temp2)]
temp2-=(y)
out=''.join(s)
print(out)

This works and doesn't use str.replace():
>>> "".join("bananaann".split("an"))
'ban'
Put it in a new function and you're done.
def replace_(original, sub_from, sub_to=""):
return sub_to.join(original.split(sub_from))
>>> replace_("bananaann", "an")
'ban'

inputS=input('string?')
inputSub=input('substring?')
s=list(inputS)
sub=list(inputSub)
print(sub)
z=len(s)-len(sub)+1
y=len(sub)
def remove_sub():
li=[] #index at which substring is present
for x in range(z):
if s[x]==sub[0]:
if y==1:
li.append(x)
continue
for temp in range(1,y):
if s[x+temp]==sub[temp]:
temp+=1
if temp==y:
li.append(x)
else:
print(x)
else:
continue
return(li)
li=remove_sub()
print(li)
temp2=0
for i in range(len(li)): '''removing substrings, works even for multiple occurences'''
del s[li[i]+temp2:(li[i]+y+temp2)]
temp2-=(y)
out=''.join(s)
print(out)

Related

Python : Create a function that takes a list of integers and strings and returns a new list with the strings filtered out

I am new to coding in Python and I am struggling with a very simple problem. There is the same question but for javascript on the forum but it does not help me.
My code is :
def filter_list(l):
for i in l:
if i != str():
l.append(i)
i = i + 1
return(l)
print(filter_list([1,2,'a','b']))
If you can help!
thanks
Before I present solution here are some problems you need to understand.
str()
str() creates a new instance of the string class. Comparing it to an object with == will only be true if that object is the same string.
print(1 == str())
>>> False
print("some str" == str())
>>> False
print('' == str())
>>> True
iterators (no +1)
You have i = i + 1 in your loop. This doesn't make any sense. i comes from for i in l meaning i looping over the members of list l. There's no guarantee you can add 1 to it. On the next loop i will have a new value
l = [1,2,'a']
for i in l:
print(i)
>>> 1
>>> 2
>>> 'a'
To filter you need a new list
You are appending to l when you find a string. This means that when your loop finds an integer it will append it to the end of the list. And later it will find that integer on another loop interation. And append it to the end AGAIN. And find it in the next iteration.... Forever.
Try it out! See the infinite loop for yourself.
def filter_list(l):
for i in l:
print(i)
if type(i) != str:
l.append(i)
return(l)
filter_list([1,2,'a','b'])
Fix 1: Fix the type check
def filter_list(l):
for i in l:
if type(i) != str:
l.append(i)
return(l)
print(filter_list([1,2,'a','b']))
This infinite loops as discussed above
Fix 2: Create a new output array to push to
def filter_list(l):
output = []
for i in l:
if type(i) != str:
output.append(i)
return output
print(filter_list([1,2,'a','b']))
>>> [1,2]
There we go.
Fix 3: Do it in idiomatic python
Let's use a list comprehension
l = [1,2,'a','b']
output = [x for x in l if type(x) != str]
print(output)
>>> [1, 2]
A list comprehension returns the left most expression x for every element in list l provided the expression on the right (type(x) != str) is true.

Remove Carriage Return from the final print statement

import re
import sys
def isValid(s):
pattern_= re.compile("[12][\d]{12}$")
return pattern_.match(s)
loop = int(input ())
output=[]
for _ in range(0, loop):
ele = int(input())
output.append(ele)
entries = ''
for x in output :
entries += str(x)+ ''
print (output ) #['0123456789012']
print (entries ) #0123456789012
print(type(entries )) #str
print(type(output )) #list
# Driver Code
for _ in range(loop):
for x in entries:
if (isValid(x)):
sys.stdout.write ("Valid Number")
break
else :
sys.stdout.write ("Invalid Number")
break
Phones Numbers starts with the digit 1 or 2 followed by exactly 12 digits i.e Phones Numbers comprises of 13 digits.
For each Phone Number, print "Valid" or "Invalid" in a new line.
The list is taking wrong input
The output generated is,
2
0123456789012
1123456789012
[123456789012, 1123456789012]
123456789012 1123456789012
<class 'str'>
<class 'list'>
Invalid NumberInvalid Number
[Program finished]
Also, I have searched on stack before posting. This looked different issue. If anything matches the error on stack please redirect me there.
2
1123456789012
0123456778901
Valid Number
Invalid Number
[Program finished]
This is what it should look like
import re
def isValid(s):
pattern_= re.compile(r'[1|2][0-9]{12}$')
return pattern_.match(s)
loop = int(input())
# no of times loops to run
output = []
for _ in range(0, loop):
output.append(input())
entries = ''
for x in output :
entries += x + ''
result = []
# Driver Code
for val in output:
if isValid(val):
result.append('Valid Number')
else:
result.append ('Invalid Number')
for i in range(len(result )-1):
print(result[i])
print(result[-1], end = " ")
This should work too.
print first converts the object to a string (if it is not already a string). It will also put a space before the object if it is not the start of a line and a newline character at the end.
When using stdout, you need to convert the object to a string yourself (by calling "str", for example) and there is no newline character.
May I also suggest to rephrase your question as it's not a logic issue but a syntax issue.
Comment:
Checked with single and multiple inputs.
Works.
Try using the below regex
def is_valid(s):
pattern_= re.compile(r'[1|2][0-9]{12}$')
return pattern_.match(s)
I am not sure, why you are appending the numbers to the entities variable. I have changed the code a bit and the regex is working fine.
def is_valid(s):
pattern_= re.compile(r'[1|2][0-9]{12}$')
return pattern_.match(s)
loop = int(input())
output = []
for _ in range(0, loop):
output.append(input())
entries = ''
for x in output :
entries += x + ''
print (output ) # ['0123456789012']
print (entries ) # 0123456789012
print(type(entries )) # str
print(type(output )) # list
# Driver Code
for val in output:
if isValid(val):
print('Valid Number')
else:
print('Invalid Number')
Input:
5
1234567891234
1893456879354
2897347838389
0253478642678
6249842352985
Output:
['1234567891234', '1893456879354', '2897347838389', '0253478642678', '6249842352985']
12345678912341893456879354289734783838902534786426786249842352985
<class 'str'>
<class 'list'>
Valid Number
Valid Number
Valid Number
Invalid Number
Invalid Number
import sys
import re
def isValid(s):
pattern_= re.compile(r'[1|2][0-9]{12}$')
return pattern_.match(s)
loop = int(input())
output = []
for _ in range(0, loop):
output.append(input())
entries = ''
for x in output :
entries += x + ''
print (output ) # ['0123456789012']
print (entries ) # 0123456789012
print(type(entries )) # str
print(type(output )) # list
# Driver Code
for val in output:
if isValid(val):
sys.stdout.write('Valid Number')
else:
sys.stdout.write('Invalid Number')
produces
1
1234567891234
['1234567891234']
1234567891234
<class 'str'>
<class 'list'>
Valid Number
[Program finished]
print always returns carriage.
Whereas sys.stdout.write doesn't.
The challenge was resolved hence.

Formatting lists to display leading zero - Python 3.x

I'm trying to create a matrix with 4 rows and 10 columns and display the leading 0 for all the single digit numbers that will randomly get generated later. This is what I would like it to look like: My teacher gave me this snippet as a way to format the numbers:
print('{:02}'.format(variable))
But when I use this in my function, it gives me the error: unsupported format string passed to list.__format__
I reworked my code and was able to get the leading zero, but now the 4x10 matrix is just 40 ints side by side. Anyone able to give me some help and an explanation?
My code:
def printMatrix(matrix):
for r in range(ROWS):
for c in range(COLS):
print('{:02}'.format(matrix[r][c]), end=' ')
def main():
matrix = [0]*ROWS
for i in range(ROWS):
matrix[i] = [0]*COLS
printMatrix(matrix)
You're really close, looks like you may just need another print() after the for-loop to put a newline after each row. Try this:
def printMatrix(matrix):
for r in range(ROWS):
for c in range(COLS):
print('{:02}'.format(matrix[r][c]), end=' ')
print()
Demo
you need a 0 in front .. i.e. {0:02}
print('{0:02}'.format(variable))
This 0 refer to the index of the parameters passed in e.g. this should work too:
print('{2:02}'.format("x", "y", variable))
Your code:
def printMatrix(matrix):
for r in range(ROWS):
for c in range(COLS):
print('{0:02}'.format(matrix[r][c]), end=' ')
def main():
matrix = [0]*ROWS
for i in range(ROWS):
matrix[i] = [0]*COLS
printMatrix(matrix)

Markov analysis - Return and recursion role

I am working on the solution of the Markov analysis in Think Python, but I do not understand the role of "Return" in the block code below.
As far as I known when the code reach return the function is cancel immediately, but isn't it unnecessary in this case, because there is a recursion here random_text(n-i) before the code reach the return statement, so the function will cancel only when the recursion is finish which mean when the for loop is over?? The question seem stupid but I am newbie in python and the recursion stuff is really confusing with me. I try to remove 'return' and it still run well.
def random_text(n=100):
start = random.choice(list(suffix_map.keys()))
for i in range(n):
suffixes = suffix_map.get(start, None)
if suffixes == None:
# if the start isn't in map, we got to the end of the
# original text, so we have to start again.
random_text(n-i)
return
word = random.choice(suffixes)
print(word, end=' ')
start = shift(start, word)
The full code is as below so you can understand what each function do.
from __future__ import print_function, division
import os
os.chdir(r"C:\Users\Hoang-Ngoc.Anh\Documents\WinPython-64bit 3.4.4.2\notebooks\docs")
import sys
import string
import random
# global variables
suffix_map = {} # map from prefixes to a list of suffixes
prefix = () # current tuple of words
def process_file(filename, order=2):
"""Reads a file and performs Markov analysis.
filename: string
order: integer number of words in the prefix
returns: map from prefix to list of possible suffixes.
"""
fp = open(filename)
skip_gutenberg_header(fp)
for line in fp:
for word in line.rstrip().split():
process_word(word, order)
def skip_gutenberg_header(fp):
"""Reads from fp until it finds the line that ends the header.
fp: open file object
"""
for line in fp:
if line.startswith('*END*THE SMALL PRINT!'):
break
def process_word(word, order=2):
"""Processes each word.
word: string
order: integer
During the first few iterations, all we do is store up the words;
after that we start adding entries to the dictionary.
"""
global prefix
if len(prefix) < order:
prefix += (word,)
return
try:
suffix_map[prefix].append(word)
except KeyError:
# if there is no entry for this prefix, make one
suffix_map[prefix] = [word]
prefix = shift(prefix, word)
def random_text(n=100):
"""Generates random wordsfrom the analyzed text.
Starts with a random prefix from the dictionary.
n: number of words to generate
"""
# choose a random prefix (not weighted by frequency)
start = random.choice(list(suffix_map.keys()))
for i in range(n):
suffixes = suffix_map.get(start, None)
if suffixes == None:
# if the start isn't in map, we got to the end of the
# original text, so we have to start again.
random_text(n-i)
return
# choose a random suffix
word = random.choice(suffixes)
print(word, end=' ')
start = shift(start, word)
def shift(t, word):
"""Forms a new tuple by removing the head and adding word to the tail.
t: tuple of strings
word: string
Returns: tuple of strings
"""
return t[1:] + (word,)
def main(script, filename='emma.txt', n=100, order=2):
try:
n = int(n)
order = int(order)
except ValueError:
print('Usage: %d filename [# of words] [prefix length]' % script)
else:
process_file(filename, order)
random_text(n)
print()
if __name__ == '__main__':
main(*sys.argv)

Inquiry about removing duplicates

Alright so I'm required to eliminate spaces and duplicate values in a list (of only numbers). Here's my code:
def eliminateDuplicates(lst):
i=0
while i<len(lst):
while lst.count(lst[i])!=1:
lst.remove(lst[i])
i=i+1
print(lst)
def main():
a=input("Enter numbers: ")
lst=list(a)
while ' ' in lst:
lst.remove(' ')
eliminateDuplicates(lst)
main()
while this method is effective and works, when the input is say
Enter numbers: 1 2 3 4 5 3 2 1 1 22
The output results in
['4', '5', '3', '1', '2']
I need my program to recognize 22 and 2 as different items so it doesn't delete the last 2 and the 2 in 22. Any suggestions?
EDIT: Sorry to the two posters that have already given me answers. I am not allowed to use the set function, and order does not matter.
This doesn't do what you think it does:
b="".join(a) # doesn't do anything useful since `a` is already a string
lst=list(b) # this is converting the string to a list of characters
Try this instead:
lst = a.split() # automatically cleans up the whitespace for you
print(list(set(lst)))
Turning a list into a set and back again is a handy way to remove duplicates. It's also quite efficient compared to the way you are doing it by scanning the list over and over
If you really want to keep the eliminateDuplicates function then it can just be
def eliminate_duplicates(lst):
return list(set(lst))
def main():
a=input("Enter numbers: ")
lst = a.split() # split automatically cleans up the whitespace
print(eliminate_duplicates(lst))
if __name__ == "__main__":
main()
Edit: since you're not allowed to use set, Collections is another fairly efficient method to remove duplicates
from collections import Counter
def eliminate_duplicates(lst):
return list(Counter(lst))
This is not quite so efficient, but still much better than two nested loops
from itertools import groupby
def eliminate_duplicates(lst):
[k for k,g in groupby(sorted(lst))]
Does order matter? If not cast it to a set and then cast it back to a list.
lst = [1,2,3,3,6,4,5,6, 3, 22]
lst2 = list(set(lst))
Also, you should probably use lst = a.split(' ') rather than join
def main():
a=input("Enter numbers: ") # Input the numbers
clean_a = a.strip(); #Cleans trailing white space.
lst=list(set(clean_a.split(' '))) #Split into tokens, and remove duplicates

Resources