I'm having trouble with the .translate function in python 3.7 - python-3.x

This is a silly repeating parrot program I wrote for practice. It worked on python 2.0, but it's not working now that I've started working with python 3.7. I keep getting this error...
TypeError: translate() takes exactly one argument (2 given)
I'm not sure what is happening.
import time
from string import whitespace, punctuation
# This prints a string up to a certain number of times equaling the number of characters in the string.
print ("I'm a parrot! Teach me a phrase! SQUAK!"),
parrot = input()
count = range(0, int(len(parrot.translate(None, punctuation).translate(None, whitespace))),
(int(len(parrot.translate(None, punctuation).translate(None, whitespace)))-(int(len(parrot.translate(None, punctuation).translate(None, whitespace))-1))))
for i in count:
print ('SQUAK!'),
print (parrot)
time.sleep(1.5)
print ('That phrase had %s letters in it! SQUAK!') % len(parrot.translate(None, punctuation).translate(None, whitespace))

str.translate was changed between Python 2 and 3. In Python 2 the second argument to str.translate() contains characters that are to be removed from the input string. In Python 3 str.translate() does not accept a second argument, instead characters that map to None in the translation table are removed.
You should be able to do this in Python 3:
parrot.translate({ord(c): None for c in punctuation + whitespace})
to remove punctuation and whitespace characters. E.g.
>>> parrot = "I'm a parrot! Teach me a phrase! SQUAK!"
>>> parrot.translate({ord(c): None for c in punctuation + whitespace})
'ImaparrotTeachmeaphraseSQUAK'
You could rewrite your code like this:
import time
from string import whitespace, punctuation
print ("I'm a parrot! Teach me a phrase! SQUAK!"),
parrot = input()
translation_table = {ord(c): None for c in punctuation + whitespace}
cleaned_parrot = parrot.translate(translation_table)
for c in cleaned_parrot:
print('SQUAK!', parrot)
time.sleep(1.5)
print('That phrase had {} letters in it! SQUAK!'.format(len(cleaned_parrot)))

Related

Can we replace an integer to English letter in a document python

I have a document and it contain numbers in between is there a way I can replace all the numbers to the English equivalent ?
eg:
My age is 10. I am in my 7th grade.
expected-o/p :
My age is Ten and I am in my seventh grade.
Thanks in advance
You'll want to take a look at num2words.
You'll have to construct regexp to catch the numbers you want to replace and pass them to num2words. Based on example provided, you also might need the ordinal flag.
import re
from num2words import num2words
# this is just an example NOT ready to use code
text = "My age is 10. I am in my 7th grade."
to_replace = set(re.findall('\d+', text)) # find numbers to replace
longest = sorted(to_replace, key=len, reverse=True) # sort so longest are replaced first
for m in longest:
n = int(m) # convert from string to number
result = num2words(n) # generate text representation
text = re.sub(m, result, text) # substitute in the text
print(text)
edited to reflect that OP wants to catch all digits

Python inserting characters in strings next to a specefic letters

I have a problem with adding p + vowel after a given vowel in a string using Python.
For example:
If I write welcome, the program would print wepelcopomepe.
You can use regex. Here is an example:
import re
s = 'welcome'
new_s = re.sub('([aeiou])', '\g<1>p\g<1>', s)
print(new_s)
> wepelcopomepe

String operations in Python

I'm trying to get into NLP using NLTK and I understand most of the code below, but I don't understand what x.sub("", word) and if not new_word in "" mean. I'm confused.
text = ["It is a pleasant evening.", "Guests, who came from the US arrived at the venue.", "Food was tasty."]
tokenized_docs = [word_tokenize(doc) for doc in text]
print(tokenized_docs)
x = re.compile("[%s]" % re.escape(string.punctuation))
token_nop = []
for sentence in tokenized_docs:
new_sent = []
for word in sentence:
new_word = x.sub('', word)
if not new_word in '':
sentence.append(new_word)
token_nop.append(sentence)
For simple things like this, Python is actually self-documenting. You can always fire up a Python interpreter and call the __doc__ function on a function to see what it does:
>>> import re
>>> print(re.compile(".*").sub.__doc__)
sub(repl, string[, count = 0]) --> newstring
Return the string obtained by replacing the leftmost non-overlapping
occurrences of pattern in string by the replacement repl.
So, we see, sub is simply the operation that does a substitution on the given regular expression pattern. (If you're unfamiliar with regular expressions in Python, check this out). So, for example:
>>> import re
>>> s = "Hello world"
>>> p = re.compile("[Hh]ello")
>>> p.sub("Goodbye", s)
'Goodbye world'
As for in, that's just checking if new_word is the empty string.

How can I delete the letter that occurs in the two strings using python?

That's the source code:
def revers_e(str_one,str_two):
for i in range(len(str_one)):
for j in range(len(str_two)):
if str_one[i] == str_two[j]:
str_one = (str_one - str_one[i]).split()
print(str_one)
else:
print('There is no relation')
if __name__ == '__main__':
str_one = input('Put your First String: ').split()
str_two = input('Put your Second String: ')
print(revers_e(str_one, str_two))
How can I remove a letter that occurs in both strings from the first string then print it?
How about a simple pythonic way of doing it
def revers_e(s1, s2):
print(*[i for i in s1 if i in s2]) # Print all characters to be deleted from s1
s1 = ''.join([i for i in s1 if i not in s2]) # Delete them from s1
This answer says, "Python strings are immutable (i.e. they can't be modified). There are a lot of reasons for this. Use lists until you have no choice, only then turn them into strings."
First of all you don't need to use a pretty suboptimal way using range and len to iterate over a string since strings are iterable you can just iterate over them with a simple loop.
And for finding intersection within 2 string you can use set.intersection which returns all the common characters in both string and then use str.translate to remove your common characters
intersect=set(str_one).intersection(str_two)
trans_table = dict.fromkeys(map(ord, intersect), None)
str_one.translate(trans_table)
def revers_e(str_one,str_two):
for i in range(len(str_one)):
for j in range(len(str_two)):
try:
if str_one[i] == str_two[j]:
first_part=str_one[0:i]
second_part=str_one[i+1:]
str_one =first_part+second_part
print(str_one)
else:
print('There is no relation')
except IndexError:
return
str_one = input('Put your First String: ')
str_two = input('Put your Second String: ')
revers_e(str_one, str_two)
I've modified your code, taking out a few bits and adding a few more.
str_one = input('Put your First String: ').split()
I removed the .split(), because all this would do is create a list of length 1, so in your loop, you'd be comparing the entire string of the first string to one letter of the second string.
str_one = (str_one - str_one[i]).split()
You can't remove a character from a string like this in Python, so I split the string into parts (you could also convert them into lists like I did in my other code which I deleted) whereby all the characters up to the last character before the matching character are included, followed by all the characters after the matching character, which are then appended into one string.
I used exception statements, because the first loop will use the original length, but this is subject to change, so could result in errors.
Lastly, I just called the function instead of printing it too, because all that does is return a None type.
These work in Python 2.7+ and Python 3
Given:
>>> s1='abcdefg'
>>> s2='efghijk'
You can use a set:
>>> set(s1).intersection(s2)
{'f', 'e', 'g'}
Then use that set in maketrans to make a translation table to None to delete those characters:
>>> s1.translate(str.maketrans({e:None for e in set(s1).intersection(s2)}))
'abcd'
Or use list comprehension:
>>> ''.join([e for e in s1 if e in s2])
'efg'
And a regex to produce a new string without the common characters:
>>> re.sub(''.join([e for e in s1 if e in s2]), '', s1)
'abcd'

using .find for multiple letters in a string

I'm working on a hobby project. I'm attempting to make a hangman game in Python. So far everything works nice. There's just one problem. If I type a letter that appears in the word two times, I can't get the second letter to appear. I've been toying around with string.find and string.count methods but to no avail. Does anyone have an idea how I would go about doing this? I'm stumped.
#!bin/bash/python
import os
import time
word = 'megalopolis'
l = len(word)
list = []
n=0
while n!=l:
list.append('-')
n+=1
os.system('cls' if os.name=='nt' else 'clear')
print list
i=3
while i!=0:
x = raw_input('Enter a letter: ')
if x in word and x!='':
print 'Good choice!'
count=word.count(x)
loc=word.find(x)
print count
print loc
list[loc]=x
os.system('cls' if os.name=='nt' else 'clear')
if '-' not in list:
break
print list
else:
print 'Sorry...'
i-=1
if i==2:
print 'You have '+`i`+' more chances.'
if i==1:
print 'You have '+`i`+' more chance!'
time.sleep(1)
os.system('cls' if os.name=='nt' else 'clear')
print list
if '-' not in list:
print 'YOU WIN!!'
else:
print 'GAME OVER!!'
x = raw_input('press enter')
If you just need the index of every character occurence:
indexes = [idx for idx, ch in enumerate(word) if ch == x]
Perhaps you should use Unidecode to keep the accents in words, it might be useful depending on the language (if not English). Also, you can use str.lower() or str.upper() methods to ensure every word and trial is in the same case.
The string module has useful constants for you (e.g. ascii_uppercase).
However, in this game you don't need to worry about any index. I've made another version for you:
#!/usr/bin/env python
from string import ascii_uppercase
word = "megalopolis".upper() # Top-secret!
trial = 3 # Total trials available (number of mistakes to lose the game)
typed = set() # Typed characters
word_letters = set(word)
while trial:
print
print "".join(ch if ch in typed else "-" for ch in word)
# Winning condition
if typed.issuperset(word_letters):
break
# Data input
x = raw_input("Enter a letter: ").upper()
# Error cases
if len(x) != 1:
print "Invalid input."
continue
if x in typed:
print "Already typed."
continue
if x not in ascii_uppercase:
print "What you typed isn't a letter."
continue
# Valid data cases
typed.add(x)
if x in word:
print "Good choice!"
else:
print "{} not found!".format(x),
trial -= 1
if trial == 1:
print "You have one more chance!"
elif trial > 1:
print "You have {} more chances.".format(trial)
else:
print 'Sorry...'
# Ending message
print
if trial:
print "YOU WIN!!"
else:
print "GAME OVER!!"
Hashbang: Your shebang should usually start with "#!/". You're probably using Windows, so the "bin" as a relative directory wasn't used by you.
"l" / l as a variable name should be avoided! It might be seen as one or lower "L" (PEP8), or even a pipe "|". PS: At the beginning of this item, I typed the same letter here twice.
There's no need to use "list" as a variable name here, and you shouldn't do, as that's a built-in name.
Multiplication like "txt" * 3 returns "txttxttxt" (it repeats the data) for both strings and lists
Neither "cls" nor "clear" worked here, showing
"TERM environment variable not set."
instead of clearing the console screen. I replaced these with an empty
"print", and removed the time sleep. Look for subprocess if you want to call something from console (although I'd also look for curses if there's a need to do some CLI visualization).
Suppose x is a string. When x == "", bool(x) is False, else bool(x) is True.
Suppose x is an integer. When x == 0, bool(x) is False, else bool(x) is True.
Avoid backticks (`). No one uses them today in Python, they doesn't exist in Python 3 and you can use the repr built-in instead. However, you probably wanted something like str(trial), "%d" % trial or "{}".format(trial).
The last "press enter" probably has to do with an operating system "auto-close-after-finish" behaviour, but you [at least] didn't need to store it in x.
I've used a generator expression. You should read here about list comprehensions if the "for" in the middle of one line is confusing for you. Python developers use generator expressions and list comprehensions all the time, you shouldn't avoid learning about them.
I replaced the original winning evaluation to a comparison between the set of characters the word originally has and the set of typed characters (both uppercase).
If there's something here you didn't understand, please ask a new question.
This SO question ought to cover it for you:
Finding multiple occurrences of a string within a string in Python
It should work just as well for individual characters as strings, considering how easy it is to form the second from the first.
So in the end, I wound up doing it this way:
if x in word and x!='':
count=word.count(x)
loc=0
while count==1 or count>1:
loc=word.find(x,loc)
list[loc]=x
loc+=1
count-=1
print 'Good choice!'
Thanks for your help everyone. I definitely learned something.

Resources