Python commacode adding and - python

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]

Related

Comma Code program in Automate the Boring Stuff

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))

Python, Output all words from a list found in a string in order of apperance

The function takes a list of words that I want to return, if they appear in the string, as a string separated by " ". However, right now they will be returned in the order of apperance in my list passed to the function. How can I modify my function so they are returned in the order of apperance in the string ?
Only similar post I found was this one which return the first word and its in python 2.x :
Grab the first word in a list that is found in a string. ( Python )
def ifExiste(set):
count_tweet_adding = 0
tempvalue = []
value = ""
x=0
old_count = count_tweet_adding
for element in set:
if (word_tweet.find(element) >= 0):
tempvalue.append(element.strip())
count_tweet_adding +=1
value = tempvalue[0]
if (old_count == count_tweet_adding):
value = "NaN"
while x < len(tempvalue)-1:
x += 1
value = value + " " + tempvalue[x]
return value
EDIT :
Here is how I did it:
I added a loop to filter words that are in both the string and my list of words and then used this filtered list with the 'brute force' method to check my string letter by letter. I also added a replace lign to take the word I picked up out of the string so I can capture it twice if it appears twice in my string.
def ifExiste(text, input_list):
count_tweet_adding = 0
tempvalue = []
value = ""
old_count = count_tweet_adding
filtered_input_list = []
for word in input_list:
if word in text:
filtered_input_list.append(word)
for length in range(len(text)):
for word in filtered_input_list:
if word in text[:length+1]:
tempvalue.append(word)
text = text[:length+1].replace(word,'')+text[length+2:]
count_tweet_adding +=1
tempvalue = map(str.strip, tempvalue)
value = " ".join(tempvalue)
if (old_count == count_tweet_adding):
value = "NaN"
return value
Here's a quick and dirty (bruteforce) solution.
Assume that you have a string of the following sort to compare against, since you mentioned the separator (or delimiter) is "".
>>> s = "herearesomewordsinastringinsomeorder"
Now assume you have a list l, the words from which you want to compare against s and document.
>>> l = ['string', 'the', 'in', 'appear', 'words', 'these', 'do']
You could then initialize a new list, newlist, to document the words in l in the same order they appear in s.
>>> newlist = []
Then you could write a for-each-in loop of the sort:
>>> for length in range(len(s)):
... for word in l:
... if word in s[:length+1] and word not in newlist:
... newlist.append(word)
Which, on evaluation, would give you:
>>> newlist
['words', 'in', 'string']
in the order they appeared in s.
You may be able do this with an expression!
def fn(s, input_list):
return list(x for x in s.split() if x in input_list)
This works by first making your string s into a list, then iterating over it, finding all the members that are in input_list
>>> fn("one two three", ["three", "two", "missing"])
['two', 'three']
This should be perfectly reasonable for small strings
If you want to create a new string, you can use " ".join()"
>>> " ".join(fn("one two three", ["three", "two", "missing"]))
'two three
If you always want to return a new string, you can directly return the joined value instead of creating a new list.
def fn(s, input_list):
return " ".join(x for x in s.split() if x in input_list)

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
.
.
.

Categories

Resources