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
.
.
.
Related
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]
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))
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="")
I'm trying to check if a string is the same as any string in the list.
This is what I coded in python:
word_split = action_one(element)
while word_split in new_element:
word_split = action_one(element)
new_element.extend(word_split)
This is action one function do:
def action_one(element):
random_position = randint(0, len(element) - 1)
if random_position == len(element) - 1:
word_split = [characters[:random_position] + characters[random_position].upper() for characters in element.split()]
else :
word_split = [characters[:random_position] + characters[random_position].upper() + characters[random_position + 1 : len(element)] for characters in element.split()]
return word_split
But the output list still have duplicate elements in it.
Can anyone point out where I did wrong?
Thanks!!
There definitely seems to be a typo on this line:
while word split in new_element:
It shouldn't be more complicated than this:
for my_string in my_list
if my_string not in my_new_list:
my_new_list.append(my_string)
I don't know what I did - it's wrong .
Can someone help me?
def insert_sequence(dna1, dna2, number):
'''(str, str, int) -> str
Return the DNA sequence obtained by inserting the second DNA sequence
at the given index. (You can assume that the index is valid.)
>>> insert_sequence('CCGG', 'AT', 2)
'CCATGG'
>>> insert_sequence('TTGC', 'GG', 2)
'TTGGGC'
'''
index = 0
result = '';
for string in dna1:
if index == number:
result = result + dna2
result = result + string
index += 1
print(result)
Here's a solution:
def insert_sequence(dna1, dna2, number):
'''(str, str, int) -> str
Return the DNA sequence obtained by inserting the second DNA sequence
at the given index. (You can assume that the index is valid.)
>>> insert_sequence('CCGG', 'AT', 2)
'CCATGG'
>>> insert_sequence('TTGC', 'GG', 2)
'TTGGGC'
'''
return dna1[:number] + dna2 + dna1[number:]
you needed an if-else loop here :
def insert_sequence(dna1, dna2, number):
result = '';
#you can use enumerate() to keep track of index you're on
for ind,x in enumerate(dna1):
if ind == number: #if index is equal to number then do this
result = result + dna2 +x
else: #otherwise do this
result = result + x
print(result)
insert_sequence('CCGG', 'AT', 2)
insert_sequence('TTGC', 'GG', 2)
output:
CCATGG
TTGGGC
There are already right working functions in other answers (specially the comment from Rakesh Pandit and the answer from JeffS), but your actual question is "why my original function doesn't work".
I copied a working version of your function, comments below:
def insert_sequence(dna1, dna2, number):
index = 0
result = ''
for character in dna1:
if index == number:
result = result + dna2
result = result + character
index += 1
print(result)
Python considers indentation, so you should print only at the end of things, outside loops and ifs.
When you "increase" your result, you do this only inside the "if" on your function, when actually you should increase "for every character in dna1", and only when/"if index == number" you should put the middle string inside.
I believe you are very new to Python or to programming in general, being probably from a biological background, but you really shouldn't iterate to get this type of string operation done, as others have shown.
Hope this helps!
You're never splitting the string apart, so you'll always prepend dna2 to dna1.
You probably want to return dna1[:number] + dna2 + dna1[number:]
You do nothing if the index is not at the insertion point, including incrementing the index. Your code needs an else and you are also printing prematurely:
def insert_sequence(dna1, dna2, number):
index = 0
result = '';
for char in dna1:
if index == number:
result = result + dna2
result = result + char
index += len(dna2) + 1
else:
result = result + char
index += 1
print(result)
mistakes made: a) parameter index is initialised to 0. b) "for sting in dia1:" should have been "for dia1_position in range(len(dia1)):" c) print result indentation is wrong and function isn't just supposed to print. It should return result. d) index need not be incremented now.
Answers are already there. Above briefly lists the mistakes made. I guess you didn't see any error because you never called the function. First error should be "number" not defined (not any more as question has been updated and parameter has number defined).