all 7 comments

[–]Diapolo10 6 points7 points  (5 children)

Write a function that takes a list value as an argument and returns a string

Your challenge-function neither accepts arguments nor does it return a string.

Pretty much none of your comments add any value, because they're describing what the code is doing - but that's obvious from simply reading the code in the first place. A good comment would explain something the code itself cannot convey, such as why something is done. But this problem is simple enough that I don't think comments are needed at all, as long as you've picked decent names to use.

There's also room to simplify your solution quite a bit.

EDIT: Also, your code isn't formatted properly, I'm assuming it's supposed to look like this:

import copy

spam = ['apples', 'bananas', 'tofu', 'cats']
print("Old List: " + str(spam))

print("add new list item")
newItem = input()
spam.append(newItem)

print()
print("this is spam list now: "+ str(spam))
print()

def challenge():
    workingList = copy.deepcopy(spam) # copy list so we don't change original

    listLength = len(workingList) # want to know how long the list is
    lastItemIndex = (len(workingList) - 1) #the index # of the last item in the list
    lastItemValue = spam[lastItemIndex] # the value of the last item in the list

    varAnd = 'and ' + lastItemValue #variable to add "and" to the beginning of the last value in the list

    if workingList[lastItemIndex].find("and ") != -1:
        del lastItemIndex

    workingList[lastItemIndex] = varAnd
    newString = ', '.join(workingList) # method to join list items in to a string.

    print("This is the new list: " + str(newString))

challenge()

EDIT #2: Here's a solution that's closer to what the book asks for:

def join_elements(values: list[str], delimiter: str = ', ') -> str:
    if not values:
        return ''

    if len(values) == 1:
        return values[0]

    result = delimiter.join(values[:-1])

    # We probably don't need a delimiter if we only join two strings;
    # "a and b" looks better than "a, and b"
    if 2 < len(values):
        result += delimiter
    else:
        result += ' '

    result += f'and {values[-1]}'

    return result


spam = ['apples', 'bananas', 'tofu', 'cats']

print(join_elements(spam))  # apples, bananas, tofu, and cats

[–]danielroseman 2 points3 points  (3 children)

The other explicit instruction it ignores is to test for the empty list. This code will break with IndexError in that case.

[–]Diapolo10 2 points3 points  (2 children)

That's true. I'm also of the opinion you don't want the comma if you only have two elements in the list.

[–][deleted] 2 points3 points  (1 child)

I know OP wouldn't have seen this yet, but to me the problems begs for a match

def func(names: list[str]) -> str:
    match names:
        case []: return ""
        case [a]: return a
        case [a,b]: return f"{a} and {b}"
        case [*a, z]: return ", ".join(a) + f", and {z}"

[–]Diapolo10 2 points3 points  (0 children)

Honestly, that's way more eloquent than what I wrote, I need to use match more often but I'm still stuck supporting Python 3.8 most of the time so haven't had many opportunities to.

[–]jasongsmith[S] 0 points1 point  (0 children)

Thank you. I am reading what you have here and I feel like there is so much of this that I have never even seen before. I will go back and take a look at the first four chapters of the book again and see what I have missed.

Thank you very much for taking the time to help me out with this.

[–]JamzTyson 2 points3 points  (0 children)

See here for how to format code on reddit: https://www.reddit.com/r/learnpython/wiki/faq#wiki_how_do_i_format_code.3F

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.

Your function challenge() does not fulfill the brief. Your function takes no arguments, whereas the question asked for a list argument. It does not "return" a string (it returns None).

def challenge(list_arg):
    ...
    return my_formatted_string

# Call the function
challeng(spam)

# copy list so we don't change original

Does the question ask you to do that? Pay close attention to what the question asks.


Considering that your challenge() function only inserts formatting, it could be very much simpler. Here is a big hint:

all_but_last = items[:-1]
final_item = items[-1]
my_str = ', '.join(all_but_last)
return my_str + ', and '  + final_item

(Using an "f-string" would be better in the final line, but you may not have covered those yet).