Automate the boring stuff with Python: Comma Code

前端 未结 29 952
深忆病人
深忆病人 2021-02-03 16:17

Currently working my way through this beginners book and have completed one of the practice projects \'Comma Code\' which asks the user to construct a program which:

相关标签:
29条回答
  • 2021-02-03 16:33

    Use str.join() to join a sequence of strings with a delimiter. If you do so for all words except for the last, you can insert ' and ' there instead:

    def list_thing(words):
        if len(words) == 1:
            return words[0]
        return '{}, and {}'.format(', '.join(words[:-1]), words[-1])
    

    Breaking this down:

    • words[-1] takes the last element of a list. words[:-1] slices the list to produce a new list with all words except the last one.

    • ', '.join() produces a new string, with all strings of the argument to str.join() joined with ', '. If there is just one element in the input list, that one element is returned, unjoined.

    • '{}, and {}'.format() inserts the comma-joined words and the last word into a template (complete with Oxford comma).

    If you pass in an empty list, the above function will raise an IndexError exception; you could specifically test for that case in the function if you feel an empty list is a valid use-case for the function.

    So the above joins all words except the last with ', ', then adds the last word to the result with ' and '.

    Note that if there is just one word, you get that one word; there is nothing to join in that case. If there are two, you get 'word1 and word 2'. More words produces 'word1, word2, ... and lastword'.

    Demo:

    >>> def list_thing(words):
    ...     if len(words) == 1:
    ...         return words[0]
    ...     return '{}, and {}'.format(', '.join(words[:-1]), words[-1])
    ...
    >>> spam = ['apples', 'bananas', 'tofu', 'cats']
    >>> list_thing(spam[:1])
    'apples'
    >>> list_thing(spam[:2])
    'apples, and bananas'
    >>> list_thing(spam[:3])
    'apples, bananas, and tofu'
    >>> list_thing(spam)
    'apples, bananas, tofu, and cats'
    
    0 讨论(0)
  • 2021-02-03 16:33

    I am a fairly new pythonista. In the question it was asked that the function return the list contents as a string in the format that the other solutions in this forum have 'printed' it. Following is (in my opinion) a cleaner solution to this problem.

    This illustrates the comma code solution of chapter 4 [Lists] in Automate The Boring Stuff.

    def comma_code(argument):
    
        argument_in_string = ''
        argument_len = len(argument)
        for i in range(argument_len):
            if i == (argument_len - 1):
                argument_in_string = argument_in_string + 'and ' + argument[i]
                return argument_in_string
    
            argument_in_string = argument_in_string + argument[i] + ', '
    
    spam = ['apples', 'bananas', 'tofu', 'cats']
    return_value = comma_code(spam)
    print(return_value)"
    
    0 讨论(0)
  • 2021-02-03 16:34

    As it was not mentioned, here's an answer with f string, for reference:

    def list_things(my_list):
        print(f'{", ".join(my_list[:-1])} and {my_list[-1]}.')
    

    An example interpolating a custom message and accepting also a string as argument:

    def like(my_animals = None):
        message = 'The animals I like the most are'
        if my_animals == None or my_animals == '' or len(my_animals) == 0:
            return 'I don\'t like any animals.'
        elif len(my_animals) <= 1 or type(my_animals) == str:
            return f'{message} {my_animals if type(my_animals) == str else my_animals[0]}.'
        return f'{message} {", ".join(my_animals[:-1])} and {my_animals[-1]}.'
    
    
    >>> like()
    >>> like('')
    >>> like([])
    # 'I don't like any animals.'
    
    >>> like('unicorns') 
    >>> like(['unicorns']) 
    # 'The animals I like the most are unicorns.'
    
    >>> animals = ['unicorns', 'dogs', 'rabbits', 'dragons']
    >>> like(animals) 
    # 'The animals I like the most are unicorns, dogs, rabbits and dragons.'
    
    0 讨论(0)
  • 2021-02-03 16:34

    This code works no matter what data types are in the lists, boolean, int, string, float, etc.

    def commaCode(spam):
        count = 0
        max_count = len(spam) - 1
    
        for x in range(len(spam)):
            if count < max_count:
                print(str(spam[count]) + ', ', end='')
                count += 1
            else:
                print('and ' + str(spam[max_count]))
    
    spam1 = ['cat', 'bananas', 'tofu', 'cats']
    spam2 = [23, '', True, 'cats']
    spam3 = []
    
    commaCode(spam1)
    commaCode(spam2)
    commaCode(spam3)
    
    0 讨论(0)
  • 2021-02-03 16:34
    def listall(lst):               # everything "returned" is class string
        if not lst:                 # equates to if not True. Empty container is always False
            return 'NONE'           # empty list returns string - NONE
        elif len(lst) < 2:          # single value lists
            return str(lst[0])      # return passed value as a string (do it as the element so 
                                    #  as not to return [])
        return (', '.join(str(i) for i in lst[:-1])) + ' and ' + str(lst[-1])
            # joins all elements in list sent, up to last element, with (comma, space) 
            # AND coverts all elements to string. 
            # Then inserts "and". lastly adds final element of list as a string.
    

    This isn't designed to answer the original question. It's to show how to define the function addressing all the matters requested by the book without being complex. I think that's acceptable as the original question posts the books "Comma Code" test. Important Note: Something I found confusing that might help others is. "a list value" means a value of type list or "an entire list" it doesn't mean an individual value (or slices) from "type list". Hope that's helpful

    Here are the samples I used to test it:

    empty = []
    ugh = listall(empty)
    print(type(ugh))
    print(ugh)
    test = ['rabbits', 'dogs', 3, 'squirrels', 'numbers', 3]
    ughtest = listall(test)
    print(type(ughtest))
    print(ughtest)
    supertest = [['ra', 'zues', 'ares'],
                ['rabbit'],
                ['Who said', 'biscuits', 3, 'or', 16.71]]
    one = listall(supertest[0])
    print(type(one))
    print(one)
    two = listall(supertest[1])
    print(type(two))
    print(two)
    last = listall(supertest[2])
    print(type(last))
    print(last)
    
    
    0 讨论(0)
  • 2021-02-03 16:35

    Others have given great one-liner solutions, but a good way to improve your actual implementation - and fix the fact that it does not work when elements are repeated - is to use enumerate in the for loop to keep track of the index, rather than using index which always finds the first occurrence of the target.

    for counter, element in enumerate(list):
        new_string = new_string + str(element)
        if counter == (len(list)-2):
            ...
    
    0 讨论(0)
提交回复
热议问题