I'm making a variation of Codecademy's pyglatin.py to make a translator that accepts and translates multiple words. However, I'm having trouble translating more than one word. I've been able to transfer the raw input into a list and translate the first, but I do not know how to reference the next item in the list. Any help would be greatly appreciated.
def piglatin1():
pig = 'ay'
original = raw_input('Enter a phrase:').split(' ')
L = list(original)
print L
i = iter(L)
item = i.next()
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
# first word translated
L = []
M = L[:]
L.append(new_word)
print L # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "y":
return piglatin()
else:
print "Okay Dokey!"
else:
print 'Letters only please!'
return piglatin1()
I was working on this problem recently as well and came up with the following solution (rather than use range, use enumerate to get the index).
for index, item in enumerate(L):
next = index + 1
if next < len(L):
print index, item, next
This example shows how to access the current index, the current item, and then the next item in the list (if it exists in the bounds of the list).
Here are a few things to note that might help.
The lines i = iter(L) and item = i.next() are unnecessary. They have no effect in this method because you are redefining item immediately afterwards in the line for item in L. Go ahead and comment out those two lines to see if it makes any changes in your output.
The looping construct for item in L will go once over every item in the list. Whatever code you write within this loop will be executed once for each item in the list. The variable item is your handle to the list element of an iteration.
If, during any iteration, you really do want to access the "next" element in the list as well, then consider using a looping construct such as for i in range(0,len(L)). Then L[i] will be the current item and L[i+1] will you give the subsequent item.
There are some slight issues with the code but I think there is one main reason why it will not repeat.
In order to process the entire string the
again = raw_input('Translate again? Y/N')
and it's succeeding lines should be brought outside the for statement.
Also you appear to be setting L to an empty string inside the loop:
L = []
The following is a modified version of your code which will loop through the entire sentence and then ask for another one.
def piglatin():
pig = 'ay'
while True:
L = raw_input('Enter a phrase:').split(' ')
M = []
for item in L:
if len(item) > 0 and item.isalpha():
word = item.lower()
first = word
if first == "a" or first == "e" or first == "i" or first == "o" or first =="u":
new_word = word + pig
print new_word
else:
new_word = word[1:] + word[0:1] + pig
M.append(new_word)
else:
print 'Letters only please!'
print M # secondary list created.
again = raw_input('Translate again? Y/N')
print again
if len(again) > 0 and again.isalpha():
second_word = again.lower()
if second_word == "n":
print "Okay Dokey!"
break
Changes made:
You don't need to cast the return of the split to a list. The split
return type is a list.
It isn't necessary to make an iterator, the for loop will do this for you.
I removed the function as the return type. I'm assuming you were attempting some form of recursion but it isn't strictly necessary.
Hope this helps.
Step by step:
If you set variable original in this way:
original = raw_input('Enter a phrase:').split()
it will be already a list, so need to additional assignment.
What is the purpose of these lines?
i = iter(L)
item = i.next()
In a loop, you assign variable to the word, when it is actually only the first letter of the word, so it’ll be better like this: first = word[0]
Then if you want to check if first is a vowel, you can just do:
if first in 'aeuoiy'
Answer to your actual question: do not assign L to an empty list!
If you want to repeat the action of a function, you can just call it again, no need to rewrite the code.
Related
I have a list that contains some strings , I want to add some predefined values before every string in a list but the value at the end of the iteration should be different
Here is the list
lst = ['USER_INVITE','USER_LEAVE','GIVEAWAY_START','GIVEAWAY_EDIT','USER_INVITE','USER_LEAVE']
the expected output is
<:878677713269968896:909470525108154399> USER_INVITE
<:878677713269968896:909470525108154399> USER_LEAVE
<:878677713269968896:909470525108154399> GIVEAWAY_START
<:878677713269968896:909470525108154399> GIVEAWAY_EDIT
<:878677713269968896:909470525108154399> USER_INVITE
<:878677686350934027:910454682219085834> USER_LEAVE
here you can see the value before USER_LEAVE is different than others
I can simply do something like this to put these values before strings without a loop
logs = '<:878677713269968896:909470525108154399>\n'.join(map(str,keys[I]))
maybe iteration will help in this case by doing something else at the end of the loop
Using iteration, and some control flow logic around identifying the last item in the list, this can be done as follows:
output_str = ""
for i, item in enumerate(lst):
if i == len(lst) - 1: # Logic for identifying the last element
prefix = '<:878677686350934027:910454682219085834>'
else: # If not the last element in the list, do this:
prefix = '<:878677713269968896:909470525108154399>'
output_str += f'{prefix} {item}\n'
output_str = ""
for item in lst[:-1]:
output_str += f'<:878677686350934027:910454682219085834> {item}\n'
output_str += f'<:878677713269968896:909470525108154399> {lst[-1]}'
You can just work on every key but the last and then combine the output at the end.
a = "\n".join('<:878677713269968896:909470525108154399>' + key for key in lst[:-1])
b = '<:878677686350934027:910454682219085834>' + lst[-1]
a + b
'<:878677713269968896:909470525108154399>USER_INVITE\n<:878677713269968896:909470525108154399>USER_LEAVE\n<:878677713269968896:909470525108154399>GIVEAWAY_START\n<:878677713269968896:909470525108154399>GIVEAWAY_EDIT\n<:878677713269968896:909470525108154399>USER_INVITE<:878677686350934027:910454682219085834>USER_LEAVE'
I'm trying to make a project in python so that whenever the program encounters a capital letter it makes a white space. So for example "helloThisIsMyProject" > hello This is My Project.
def project(w):
lst = []
for i in w:
lst.append(i)
for letter in lst:
if letter.isupper():
index = lst.index(letter)
lst.insert(index, " ")
continue
return "".join(lst)
print(project("helloThisIsMyProject"))
I'm having a problem with insert() and the for loop because the for loop is endlessly looping over the "T" from "This". I tried using continue to skip the letter T but it didn't fix my problem.
Those 1st three lines are simply
lst = list(w)
But you would find this more convenient:
lst = []
for letter in w:
if letter.isupper():
lst.append(" ")
lst.append(letter)
That is, rather than producing a list and going back to fix it up,
you could have it correct from the outset.
You can conditionally output a SPACE before you output the letter.
If you prefer to do it with a list comprehension,
you might enlist the aid of a helper:
def adjust(s: str) -> str:
"""Returns the input string, possibly whitespace adjusted."""
return " " + s if s.isupper() else s
lst = [adjust(letter)
for letter in w]
or more compactly:
lst = list(map(adjust, w))
You could use a join with a list comprehension that adds the space to individual characters:
def spaceCaps(w):
return "".join(" "*c.isupper()+c for c in w)
spaceCaps("helloThisIsMyProject")
'hello This Is My Project'
You could also use the sub() function from the regular expression module:
import re
def spaceCaps(w):
return re.sub("([A-Z])",r" \1",w)
I'm taking the MIT DS&A algorithm course and on the document distance problem, we have to parse a file into a list of words, then count the frequency of each word in the file. I have a hard time comprehending the following function:
def count_frequency(word_list):
"""
Return a list giving pairs of form: (word,frequency)
"""
L = []
for new_word in word_list:
for entry in L:
if new_word == entry[0]:
entry[1] = entry[1] + 1
break
else:
L.append([new_word,1])
return L
Why do we compare new_word to entry[0]?
a. What if L is empty? What do we compare new_word to?
b. Why do we compare new_word to entry[0] specifically? Why don't we do something like
if new_word in L
c. Why do we need to use break?
Why is the else block 1 tab to the right of the earlier if block? When I tried to indent the else block, an indentation error would show up.
Thank you for your help!
The list L contains two-item entries due to L.append([new_word,1]). If L is empty the for would not be entered, so there is no problem with entry[0].
entry[0] is a word and entry[1] is a count. You can't say if new_word in L because it is not just a list of strings.
break stops the for once a word is found.
for/else is a thing in Python. The else runs if the for completes without interruption (a break in this case). If new_word isn't in L, the for won't break and the new word and a count of 1 is added to L.
FYI, the built-in collections.Counter() would return similar results.
I'm starting out here and love list comprehension. I found this following line of code for a practice problem of capitalizing every other letter in a string and it makes sense to me. The problem I'm hoping to get help with is figuring out how to write this code normally (for loop, if statements, etc. Beginners stuff) without list comprehension.
Here's the code that I started with that I want to break down:
s = input('Please enter a string: ')
answer = ''.join(char.upper() if idx % 2 else char.lower() for idx, char in enumerate(s))
print(answer)
And here is what I thought was a proper code to reproduce what this one above was doing:
s = input('Please enter a string: ')
for idx, char in enumerate(s):
if idx % 2:
s = char.upper()
else:
s = char.lower()
answer = ''.join(s)
print(answer)
If I were to type Hello, I should get hElLo, but instead I get o
I'd appreciate any advice or tips on how to proceed here. Thanks!
Technically you're using a generator expression, and not a list comprehension. But the result is similar in this case.
You're reading input into s, but then you're reassigning s in each iteration, and then you're joining s.
You need to have a different variable. For the input and for the capitalized list. What a generator expression does is to return one value at a time, instead of building the whole capitalized list at once. But here you will need to declare it.
Also, it doesn't make sense to assign answer in each iteration, the join is the last thing you need to do, once your capitalized list is prepared.
This should work:
toCapitalize = input('Please enter a string: ')
capitalizedList = []
for idx, char in enumerate(toCapitalize):
if idx % 2:
capitalizedList.append(char.upper())
else:
capitalizedList.append(char.lower())
answer = ''.join(capitalizedList)
print(answer)
In case this helps, I've tried to reflect what line goes with what part of the generator expression below:
for idx, char in enumerate(toCapitalize): # for idx, char in enumerate(s)
if idx % 2: capitalizedList.append(char.upper()) # char.upper() if idx % 2
else: capitalizedList.append(char.lower()) # else char.lower()
answer = ''.join(capitalizedList) # answer = ''.join()
Again, the capitalizedList variable is implicit in the generator expressions or list comprehensions.
Generator expressions
To understand generator expressions look at this code:
capitalize = 'hello'
generator = (char.upper() if idx % 2 else char.lower() for idx, char in enumerate(capitalize))
print(next(generator)) # h
print(next(generator)) # E
print(next(generator)) # l
print(next(generator)) # L
print(next(generator)) # o
print(next(generator)) # raises a StopIteration exception, we've reached the end.
Each call to next() calculates the result of the next iteration on the fly. Which is more memory efficient than building a whole list at once when you have big lists. In your case, the call to join() consumes all the generator, and joins the values returned.
As a list comprehension
Your code as a list comprehension would be:
s = input('Please enter a string: ')
answer = ''.join([ char.upper() if idx % 2 else char.lower() for idx, char in enumerate(s) ])
print(answer)
As I explained above, the difference is that here we're building a whole list at once, the generator is only returning one value at a time.
Your code as a generator
And finally, to be technically correct your code would be equivalent to this:
def generator(s):
for idx, char in enumerate(s):
if idx % 2:
yield char.upper()
else:
yield char.lower()
answer = ''.join(generator(s))
print(answer)
That's how you build a generator in Python.
I believe the output I'm getting is a product of sloppy code somewhere, but I can't seem to get it. What I want my function to do is make a new list of the elements in a list it's being passed, in those elements' Pig-Latin translation. I've got the function working, but it makes all of the new list elements the Pig-Latin translation of only the first element in the list being passed to the function, even though I'm using an index to iterate through the elements of the passed list.
def pigLatin(targetlist):
newlist = ()
listnewlist = list(newlist)
index = 0 # gets incremented
firstletter = targetlist[index][0]
word = targetlist[index][1:]
print('Words made into Pig Latin: ')
while index < len(targetlist):
listnewlist.append(word + firstletter + 'ay')
index += 1
print(listnewlist)
which, after user input is "how now brown cow", displays:
['owhay', 'owhay', 'owhay', 'owhay']
word and firstletter are both computed outside of the loop and keep the value of first word of the targetlist.
IMHO, you should write :
def pigLatin(targetlist):
newlist = ()
listnewlist = list(newlist)
index = 0 # gets incremented
print('Words made into Pig Latin: ')
while index < len(targetlist):
firstletter = targetlist[index][0]
word = targetlist[index][1:]
listnewlist.append(word + firstletter + 'ay')
index += 1
print(listnewlist)