Comma Code program in Automate the Boring Stuff - python

I am trying to learn Python by working my way through 'Automate the Boring Stuff with Python'. I'm currently at chapter 4. The practice project I'm currently trying to build is as follows:
Say you have a list value like this:
spam = ['apples', 'bananas', 'tofu', 'cats']
Write a function that takes a list value as an argument and returns a string with all the items separated by a comma and a space, with and inserted before the last item. For example, passing the previous spam list to the function would return 'apples, bananas, tofu, and cats'. But your function should be able to work with any list value passed to it.
I have tried to find some answers online, but the programs online look very different from the one I have written. I was wondering how to fix my program. Currently it is only returning the first list item to me. Here is my code:
randomlist = []
while True:
print('Add something to the list: ')
listitem = input()
if listitem == '':
break
randomlist = randomlist + [listitem]
def commaplacer(somelist): #function
for i in range(len(somelist)): #this reiterates the list
if len(somelist)>i:
return somelist[i]
elif len(somelist)==i:
return 'and' + somelist[i]
else:
break
result = commaplacer(randomlist)
print(result)

When you return from a function, it means you don't want it to run any more. I think your return statements cause it to exit before you intend.
Instead, I think you should initialize your output as an empty string and then build it up as you move through the list. At the end of the loop, return output to send the completed string back.
I think your loop logic can be simplified to 2 cases. Either the item is the last in the list len(somelist)-1 == i and we need to add the 'and' or it is not the last item and we just need to put a comma.
Here's an example:
randomlist = ['Lions', 'tigers', 'bears, oh my!']
def commaplacer(somelist): # function
output = ''
for i in range(len(somelist)):
if len(somelist)-1 == i:
output += 'and ' + somelist[i]
else:
output += somelist[i] + ', '
return output
result = commaplacer(randomlist)
print(result)
will output
Lions, tigers, and bears, oh my!

You can consolidate the code to 3 lines in the function.
def commaplacer(somelist): #function
if not somelist: return ''
elif len(somelist) == 1: return somelist[0]
else: return ', '.join(somelist[:-1])+', and ' + somelist[-1]
#line 1: check if list is empty. If yes, return empty string
#line 2: check if list has only one value. If yes, return only first value
#line 3: since list has more than one value, use 'join' function
#join all values until last one. add ', and ' then add last value
Now you can call the function to get the desired result.
result = commaplacer(randomlist)
print(result)
The result will be:
#when you enter nothing, you get an empty string in return
>>> Add something to the list:
>>>
>>>
#when you enter only one value to the list
>>> Add something to the list:
>>> good
>>>
>>> good
#when you enter a few values to the list
>>> Add something to the list:
>>> apple
>>> Add something to the list:
>>> banana
>>> Add something to the list:
>>> carrot
>>> Add something to the list:
>>> egg
Add something to the list:
apple, banana, carrot, and egg

spam = []
def coma(listName):
output = ''
for i in range(len(listName):
if i==0:
output = listName[i]
elif i == len(listName) -1:
output += ', and ' + listName[i]
else:
output += ', ' + listName[i]
return output
print(coma(spam))

Related

Python commacode adding and

I'm doing an assignment where we have to write a comma code as described from the book
Say you have a list value like this:
spam = ['apples', 'bananas', 'tofu', 'cats']
Write a function that takes a list value as an argument and returns a string with all the items separated by a comma and a space, with and inserted before the last item. For example, passing the previous spam list to the function would return apples, bananas, tofu, and cats. But your function should be able to work with any list value passed to it.
We are to write it with these details:
In your program, create four lists as follows:
animalList1 = ['dog', 'cat', 'bird', 'tiger', 'lion', 'camel']
animalList2 = ['elephant', 'alligator']
animalList3 = ['horse']
animalList4 = []
When you run your program, pass each list to the commaCode() function and then print out the result as shown in the Example Output.
I'm really stuck and don't know if I'm heading in the right direction. This is my code so far:
animalList1 = ['dog', 'cat', 'bird', 'tiger', 'lion', 'camel']
animalList2 = ['elephant', 'alligator']
animalList3 = ['horse']
animalList4 = []
spam = [animalList1, animalList2, animalList3, animalList4]
def commacode(list):
spam[-1] = 'and ' + str(spam-[1])
for i in range(len(spam)-1):
spam[i] = str(spam[i]) + ','
stringList = ''
for i in range(len(spam)):
stringList = stringList + str(spam[i])
print(stringList)
print(commacode(spam))
This code also works. Firstly, you have 4 lists in the spam list. So you need to iterate over it. That is what the last 2 lines do. Each time a list is passed as a parameter to the commacode function. According to your expectations, the length of the list is identified to check if the length is 1. If the length is 1 it means there is one item. So that is printed out. If the length is 0 nothing is done. If the length is not zero then items in the list are iterated and concatenated to the string with a comma. Every item is checked on whether it is the last item. If it is the last item, the string will contain and as well.
from varname import nameof
animalList1 = ['dog', 'cat', 'bird', 'tiger', 'lion', 'camel']
animalList2 = ['elephant', 'alligator']
animalList3 = ['horse']
animalList4 = []
spam = [animalList1, animalList2, animalList3, animalList4]
name_of_list = [nameof(animalList1), nameof(animalList2), nameof(animalList3), nameof(animalList4)]
string = ""
counter = 0
def commacode(list, list_name):
global string
length = len(list)
if length == 1:
string = list[0]
elif length != 0:
for item in list:
if list.index(item) == length-1:
string = string + "and " + str(item)
else:
string = string + str(item) + ", "
else:
string = "-"
print(f"{list_name}: {string}")
string = ""
for list in spam:
commacode(list, name_of_list[counter])
counter += 1
The output that I got:
animalList1: dog, cat, bird, tiger, lion, and camel
animalList2: elephant, and alligator
animalList3: horse
animalList4: -
def foo(mylist):
if len(mylist) == 0:
return ""
elif len(mylist) == 1:
return mylist[0]
else:
return ", ".join(mylist[:-1]) + " and " + mylist[-1]
you need to add exception cases.
using .join makes things easy.
learn about join here:
https://www.geeksforgeeks.org/join-function-python/
learn about list indexing and slicing here:
https://towardsdatascience.com/the-basics-of-indexing-and-slicing-python-lists-2d12c90a94cf
I assume that you are not allowed to use join here. You must first take care of special cases for empty lists and singletons, then add all elements with another special processing for the last one.
Here is a possible Python code:
def commacode(lst):
# an empty list gives a blank string
if len(lst) == 0:
cr = ''
# a single element list returns its element
elif len(lst) == 1:
cr = lst[0]
# else all elements are joined with ' ,' except last with ', and'
else:
cr = lst[0]
# list has at least 2 elements so list[1:-1] is defined
# (it is at least empty for just 2 elements)
for elt in lst[1:-1]:
cr += ', ' + elt
# special processing for the last element
cr += ', and ' + lst[-1]
return cr
for lst in spam:
print(commacode(lst))
With your data, it gives as expected:
dog, cat, bird, tiger, lion, and camel
elephant, and alligator
horse
>>>
(I have added a prompt display make the last empty line visible)
If you can use join, the else part could be:
else:
# list has at least 2 elements so list[1:-1] is defined
# (it is at least empty for just 2 elements)
cr = ', '.join(lst[:-1]
# special processing for the last element
cr += ', and ' + lst[-1]

Joining words together with a comma, and "and"

I'm working through 'Automate the Boring Stuff with Python'. I can't figure out how to remove the final output comma from the program below. The goal is to keep prompting the user to input values, which are then printed out in a list, with "and" inserted before the end. The output should look something like this:
apples, bananas, tofu, and cats
Mine looks like this:
apples, bananas, tofu, and cats,
That last comma is driving me NUTS.
def lister():
listed = []
while True:
print('type what you want to be listed or type nothing to exit')
inputted = input()
if inputted == '':
break
else:
listed.append(inputted+',')
listed.insert(-1, 'and')
for i in listed:
print(i, end=' ')
lister()
You can avoid adding commas to each string in the list by deferring the formatting to print time. Join all the items excluding the last on ', ', then use formatting to insert the joined string with the last item conjuncted by and:
listed.append(inputed)
...
print('{}, and {}'.format(', '.join(listed[:-1]), listed[-1]))
Demo:
>>> listed = ['a', 'b', 'c', 'd']
>>> print('{}, and {}'.format(', '.join(listed[:-1]), listed[-1]))
a, b, c, and d
The accepted answer is good, but it might be better to move this functionality into a separate function that takes a list, and also handle the edge cases of 0, 1, or 2 items in the list:
def oxfordcomma(listed):
if len(listed) == 0:
return ''
if len(listed) == 1:
return listed[0]
if len(listed) == 2:
return listed[0] + ' and ' + listed[1]
return ', '.join(listed[:-1]) + ', and ' + listed[-1]
Test cases:
>>> oxfordcomma([])
''
>>> oxfordcomma(['apples'])
'apples'
>>> oxfordcomma(['apples', 'pears'])
'apples and pears'
>>> oxfordcomma(['apples', 'pears', 'grapes'])
'apples, pears, and grapes'
This will remove the comma from the last word.
listed[-1] = listed[-1][:-1]
The way it works is listed[-1] gets the last value from the list. We use = to assign this value to listed[-1][:-1], which is a slice of the last word from the list with everything before the last character.
Implemented as shown below:
def lister():
listed = []
while True:
print('type what you want to be listed or type nothing to exit')
inputted = input()
if inputted == '':
break
else:
listed.append(inputted+',')
listed.insert(-1, 'and')
listed[-1] = listed[-1][:-1]
for i in listed:
print(i, end=' ')
lister()
Modifying your code a little bit...
def lister():
listed = []
while True:
print('type what you want to be listed or type nothing to exit')
inputted = input()
if inputted == '':
break
else:
listed.append(inputted) # removed the comma here
print(', '.join(listed[:-2]) + ' and ' + listed[-1]) #using the join operator, and appending and xxx at the end
lister()
listed[-1] = listed[-1][:-1]
This will truncate the final character of the final string in listed.
Lots of ways to do it, but how about this?
# listed[-1] is the last element of the list
# rstrip removes matching characters from the end of the string
listed[-1] = listed[-1].rstrip(',')
listed.insert(-1, 'and')
for i in listed:
print(i, end=' ')
You'll still be printing a space at the end of the line, but I guess you won't see it and thus won't care. :-)
I would do it using an f-string (a formatted string literal, available in Python 3.6+):
def grammatically_join(words, oxford_comma=False):
if len(words) == 0:
return ""
if len(words) == 1:
return listed[0]
if len(words) == 2:
return f"{listed[0]} and {listed[1]}"
return f'{", ".join(words[:-1])}{"," if oxford_comma else ""} and {words[-1]}'
If you don't need the Oxford comma, then you can simplify the code and remove the extra edge case for len(words) == 2:
def grammatically_join(words):
if len(words) == 0:
return ""
if len(words) == 1:
return listed[0]
return f'{", ".join(words[:-1])} and {words[-1]}'
Assuming you're okay with a comma if there are only two items, this is fairly compact:
def commaize(items):
return ', and'.join(', '.join(items).rsplit(',', 1))
Which behaves like this:
>>> commaize([])
''
>>> commaize(['apples'])
'apples'
>>> commaize(['apples', 'bananas'])
'apples, and bananas'
>>> commaize(['apples', 'bananas', 'tofu', 'cats'])
'apples, bananas, tofu, and cats'

Print a list of items separated by commas but with the word "and" before the last item

I've been working on this for two days. This is what the assignment states:
Say you have a list value like this: listToPrint = ['apples', 'bananas', 'tofu', 'cats'] Write a program that prints a list with all the items separated by a comma and a space, with "and" inserted before the last item. For example, the above list would print 'apples, bananas, tofu, and cats'. But your program should be able to work with any list not just the one shown above. Because of this, you will need to use a loop in case the list to print is shorter or longer than the above list.
This is what I have thus far:
listToPrint = []
while True:
newWord = input("a, b, and c ")
if newWord == "":
break
else:
listToPrint.append(newWord)
The code you've shown appears to be solving a different problem than what your assignment wants you to do. The assignment is focused on printing the values from a provided list, while your code is all about inputing items from the user and putting them into a list. It could make sense to do one and then the other, but for the assignment that you've given in the comments, the input code is completely irrelevant.
Here's how I'd solve that assignment (probably with code that you don't understand yet):
print("{}, and {}".format(", ".join(list_to_print[:-1]), list_to_print[-1]))
A more "novice friendly" approach would look more like this:
for item in list_to_print[:-1]:
print(item, end=', ')
print('and', list_to_print[-1])
Here is how I would do it, but be careful if this is for school. Your instructor will frown on you if any of the things I have done below are using features or techniques that haven't yet been covered.
listToPrint = ['a', 'b', 'c']
def list_to_string(L, sep = '', last_sep = None):
if last _sep is None:
return sep.join(L)
else:
return sep.join(L[:-1]) + last_sep + L[-1]
print(list_to_string(listToPrint, sep = ', ', last_sep = ', and '))
Here's a bit more of a beginner version:
listToPrint = ['a', 'b', 'c']
list_length = len(listToPrint)
result = ""
count = 0
for item in listToPrint:
count = count + 1
if count == list_length:
result = result + "and " + item
else:
result = result + item + ", "
This one doesn't work with only one item in the list.
Beginner Version:
x = ['apples', 'bananas', 'tofu', 'cats']
print("'", end='')
for i in range(len(x)-2):
print(x[i], end=', ')
print(str(x[-2])+' and '+str(x[-1]),end='')
print("'")
Output: 'apples, bananas, tofu and cats'
#printing the first element sep. so the list works
print(listToPrint[0], end="")
for i in range(1, len(listToPrint)-1):
print("," + listToPrint[i], end="") #this prints the middle elements
if(len(listToPrint) > 1):
print( " and " + listToPrint[-1], end="")

Is there a better way to accomplish this python excercise? (Beginner)

I'm just starting to learn Python and I'm going through an exercise at the end of a chapter. So far, all I've learned about in the book is the very basics, flow control, functions, and lists.
The exercise is:
Comma Code
Say you have a list value like this:
spam = ['apples', 'bananas', 'tofu', 'cats']
Write a function that takes a list value as an argument and returns
a string with all the items separated by a comma and a space, with "and"
inserted before the last item. For example, passing the previous spam list to
the function would return 'apples, bananas, tofu, and cats'. But your function
should be able to work with any list value passed to it.
To solve this, I use the following code (python 3.x.x). I'm wondering if there is a better way to do this. It took a little trial and error, but I fumbled through it until I got this:
myList = ['apples', 'bananas', 'tofu', 'cats']
myList2 = ['apples', 'bananas', 'tofu', 'cats', 'added1', 'added2']
def listFunc(List):
x = 0
for i in List:
x += 1
if x < len(List):
print(i, end=' ')
elif x == len(List):
print('and ' + i)
listFunc(myList2)
Another way to accomplish this would be to use slices and joins:
def listFunc(lst):
if len(lst) == 0: return ''
if len(lst) == 1: return lst[0]
return ", and ".join([", ".join(lst[:-1]), lst[-1]])
Here's a more readable version of the above function using the same core concepts.
def listFunc(lst):
if len(lst) == 0: return '' #no elements? empty string
if len(lst) == 1: return lst[0] #one element? no joining/separating to do, just give it back
firstPart = lst[:-1] #firstPart is now everything except the last element
retFirst = ", ".join(firstPart) #retFirst is now the first elements joined by a comma and a space.
retSecond = ", and " + lst[-1] #retSecond is now ", and [last element]"
return retFirst + retSecond;
The only potentially confusing bits here I think are the slice syntax, negative indices, and string.join
The code lst[:-1] means get everything in lst excepting the last element This is a list slice
The code lst[-1] means get the last element in lst This is negative indexing
And finally, the code ", ".join(firstPart) means get a string containing each element in firstPart separated by a comma and a space
Here is a simple version of the function that doesn't use anything very "fancy" and should be understandable by a beginner. Slicing is probably the most advanced stuff here but should be ok if you went through lists. It also handles two special cases of an empty list and one-item list.
def listFunc(List):
if len(List) == 0: return ''
if len(List) == 1: return List[0]
value = List[0]
for item in List[1:-1]:
value = value + ', ' + item
return value + ', and ' + List[-1]
This is not the way you would normally do it in Python but should be good for learning purposes.
Let's have fun with Python 3 and keep it simple:
def listFunc(myList):
*rest, last = myList
return ", ".join(rest) + (", and " if rest else "") + last
You can make it slightly shorter using enumerate:
def printList():
# x will be the string in the list, y will be an integer
aString = ""
for (y,x) in enumerate(myList):
if y < len(myList) - 1:
aString = aString + x + ", "
else:
aString = aString + "and " + x
.
.
.

Reference next item in list: python

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.

Categories

Resources