Joining words together with a comma, and "and" - python

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'

Related

How to acces the next value in for loop

So im trying to get first letters of words(excluding first word, i already solved that) in a sentence.
But it appends spaces to the list.
Would appreciate if you help.
Here's the code:
lst = []
for t in (input()):
if t == " ":
lst.append(t)
print(*lst, sep="")
input1: asd dfd yjs
output1: dy
just this:
''.join([s[0] for s in input().split()[1:]])
step by step:
if input() returns asd dfd yjs
split string (more):
input().split() # output: ['asd', 'dfd', 'yjs']
sub list (more):
input().split()[1:] # output: ['dfd', 'yjs']
one line loop (more):
[s[0] for s in ['dfd', 'yjs']] # output: ['d', 'y']
sub string (more):
s="dfd"
s[0] # output: d
concat list of strings (more):
''.join(['d', 'y']) # output: dy
You're getting spaces because that's what you asked for. Read your code out loud and it will probably make sense:
if t == " ":
lst.append(t)
If t is a space, append it to lst
Seems clear that you will only get spaces.
You want the character after t to be appended. There's two ways to do that using your for loop method: 1) if t is a space, append the next character; 2) if the previous character was a space, append t. Here's how you might implement #2:
lst = []
prev_char = None
for t in (input()):
if prev_char == " ":
lst.append(t)
prev_char = t
print(*lst, sep="")
This will print the first character of ever word except the first word. Initialize last_char to a space to include the first word.
You may
split your sentence into words using x.split()
remove the first word, using a slice [1:] (from index 1 to the end)
then keep only the first char of each word and concatenate it to a result string
x = input(">")
result = ""
for word in x.split()[1:]:
result += word[0]
print(result) # dy
Using a generator and str.join :
x = input(">")
result = ''.join(word[0] for word in x.split()[1:])
You could use str.split:
lst = [s[0] for s in input().split()[1:]]
A simple example:
lst = []
get_next = False
for t in input():
if t == " ":
get_next = True
elif get_next:
lst.append(t)
get_next = False
print(*lst, sep="")
A lot great answers already and this is good case for split. If you specifically need to collect the next token after a special token in a stream of tokens, here are some other options:
inp = "asd dfd yjs"
lst = []
for a, b in zip(inp[:-1],inp[1:]):
if a == " ":
lst.append(b)
print(*lst, sep="")
# With comprehensions - my choice
print("".join([b for a, b in zip(inp[:-1],inp[1:]) if a == " "]))
# With functional approach
from functools import reduce
from operator import add, itemgetter
def has_prior_space(x):
return x[0] == " "
print(reduce(add, map(itemgetter(1), filter(has_prior_space, zip(inp[:-1], inp[1:])))))
In Python 3.10, there will be a new pairwise iterator that does this type of "2 at a time" iteration specifically: zip(inp[:-1],inp[1:])
Use Array join():
''.join(lst)

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]

Appending a char to an empty list

I am very new to programming, so sorry for a basic question. I am trying to write a function that will take a string in which words are divided by ',' and return a list of these words (the Split method). My code is:
def str_to_list(my_shop_str):
my_shop_list = ['']
word_in_list = 0
for letter in my_shop_str:
if letter != ',':
my_shop_list[word_in_list] += letter
else:
word_in_list += 1
my_shop_list + ['']
return my_shop_list
print(str_to_list("Milk,Cottage,Tomatoes")) should look like [Milk, Cottage, Tomatoes]
but I am keep getting IndexError: list index out of range.
I read some answers here and couldn't find something to work.
Can anyone explain what is wrong.
list has the method append so a solution will be something like this:
def str_to_list(my_shop_str):
my_shop_list = ['']
word_in_list = 0
for letter in my_shop_str:
if letter != ',':
my_shop_list[word_in_list] += letter
else:
word_in_list += 1
my_shop_list.append('')
return my_shop_list
PS: Do not forgot about empty spaces between words in string like "aaa, bbb, ccc" will be ['aaa', ' bbb', ' ccc'] with spaces.
def sp(s):
l =[]
while True:
comma = s.find(',')
if comma == -1:
l.append(s)
break
l.append(s[:comma])
s = s[comma+1:]
print(l)
this is a simplified version hope it helps.
Simplest Way:
We can use an inbuilt split function.
def Convert(string):
# split the string whenever "," occurs
# store the splitted parts in a list
li = list(string.split(","))
return li
# Driver code
str1 = "Hello,World"
print(Convert(str1))
Output:
["Hello", "World"]

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

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

Categories

Resources