Je travaille actuellement sur ce livre pour débutants et j'ai terminé l'un des projets de pratique «Comma Code» qui demande à l'utilisateur de construire un programme qui:

prend une valeur de liste comme argument et retourne une chaîne avec tous les éléments séparés par une virgule et un espace, avec et inséré avant le dernier élément. Par exemple, transmettre la liste de spam ci-dessous à la fonction retournerait «pommes, bananes, tofu et chats». Mais votre fonction devrait pouvoir travailler avec n'importe quelle valeur de liste qui lui est transmise.

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

Ma solution au problème (qui fonctionne parfaitement bien):

spam= ['apples', 'bananas', 'tofu', 'cats']
def list_thing(list):
    new_string = ''
    for i in list:
        new_string = new_string + str(i)
        if list.index(i) == (len(list)-2):
            new_string = new_string + ', and '
        elif list.index(i) == (len(list)-1):
            new_string = new_string
        else:
            new_string = new_string + ', '
    return new_string

print (list_thing(spam))

Ma seule question, est-il possible de raccourcir mon code? ou le rendre plus «pythonique»?

Voici mon code.

def listTostring(someList):
    a = ''
    for i in range(len(someList)-1):
        a += str(someList[i])
    a += str('and ' + someList[len(someList)-1])
    print (a)

spam = ['apples', 'bananas', 'tofu', 'cats']
listTostring(spam)

Production: pommes, bananes, tofu et chats

3
Sutharsan Sethurayar 8 août 2016 à 11:37

23 réponses

Meilleure réponse

Utilisez str.join() pour joindre une séquence de chaînes avec un délimiteur. Si vous le faites pour tous les mots sauf pour le dernier, vous pouvez y insérer ' and ' à la place:

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

Décomposer cela:

  • words[-1] prend le dernier élément d'une liste. words[:-1] tranche la liste pour produire une nouvelle liste avec tous les mots sauf le dernier.

  • ', '.join() produit une nouvelle chaîne, avec toutes les chaînes de l'argument à str.join() jointes à ', '. S'il n'y a que un élément dans la liste d'entrée, cet élément est retourné, non joint.

  • '{}, and {}'.format() insère les mots joints par une virgule et le dernier mot dans un modèle (complet avec une virgule Oxford).

Si vous passez dans une liste vide, la fonction ci-dessus lèvera une exception IndexError; vous pouvez spécifiquement tester ce cas dans la fonction si vous pensez qu'une liste vide est un cas d'utilisation valide pour la fonction.

Donc, ce qui précède joint tous les mots sauf le dernier avec ', ', puis ajoute le dernier mot au résultat avec ' and '.

Notez que s'il n'y a qu'un seul mot, vous obtenez ce seul mot; il n'y a rien à joindre dans ce cas. S'il y en a deux, vous obtenez 'word1 and word 2'. Plus de mots produisent 'word1, word2, ... and lastword'.

Démo:

>>> 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'
12
Martijn Pieters 8 août 2016 à 09:44

Comme cela n'a pas été mentionné, voici une réponse avec f chaîne, pour référence:

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

Un exemple interpolant un message personnalisé et acceptant également une chaîne comme 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
Анна 13 mars 2019 à 03:18

Comme la fonction doit fonctionner pour toutes les valeurs de liste qui lui sont transmises, y compris les entiers, elle devrait donc être en mesure de renvoyer / imprimer toutes les valeurs, c'est-à-dire sous la forme str (). Mon code pleinement fonctionnel ressemble à ceci:

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

def commacode(words):

    x = len(words)

    if x == 1:
        print(str(words[0]))
    else:
        for i in range(x - 1):
            print((str(words[i]) + ','), end=' ')
        print(('and ' + str(words[-1])))

commacode(spam)
1
Adam 3 sept. 2017 à 15:08

L'instruction de format est plus propre.

Cela a également fonctionné pour moi:

def sentence(x):
    if len(x) == 1:
        return x[0]
    return (', '.join(x[:-1])+ ' and ' + x[-1])
2
nnaji 10 mai 2017 à 20:54

J'ai utilisé une approche différente. Je suis un débutant, donc je ne sais pas si c'est la façon la plus propre de le faire. Cela m'a semblé le moyen le plus simple:

spam = ['apples', 'pizza', 'dogs', 'cats']

def comma(items):
    for i in range(len(items) -2):
        print(items[i], end=", ")# minor adjustment from one beginner to another: to make it cleaner, simply move the ', ' to equal 'end'. the print statement should finish like this --> end=', '
    print(items[-2] + 'and ' + items[-1]) 

comma(spam)

Ce qui donnera la sortie:

apples, pizza, dogs and cats
6
jonchuckaugusts 1 janv. 2018 à 07:37

Celui-là gagne pour la simplicité Hein.

Seul, l'auteur a précisé:

"votre fonction devrait pouvoir fonctionner avec n'importe quelle valeur de liste qui lui est transmise."

Pour accompagner les non chaînes, ajoutez des balises str() à toutes les fonctions [i].

spam = ['apples', 'bananas', 'tofu', 'cats', 'bears', 21] def pList(x): for i in range(len(x) - 2): print(str(x[i]) + ', ', end='') print(str(x[-2]) + ' and ' + str(x[-1])) pList(spam)

0
Bojangles 14 déc. 2016 à 03:53

Mon interprétation de la question est telle qu'un seul élément de la liste serait également le dernier élément de la liste et, en tant que tel, aurait besoin du «et» inséré avant, ainsi qu'une liste de deux éléments renvoyant les deux avec «, and» entre eux. Il n'est donc pas nécessaire de traiter séparément une ou deux listes d'éléments, uniquement les n premiers éléments et le dernier élément. Je noterais également que, même s'ils sont excellents, de nombreux autres articles utilisent des modules et des fonctions non décrits dans le texte Automatiser les trucs ennuyeux au moment où l'élève rencontre cette question (un élève comme moi avait vu join et { {X2}} ailleurs, mais a tenté d'utiliser uniquement ce qui avait été enseigné dans le texte).

def commacode(passedlist):
    stringy = ''
    for i in range(len(passedlist)-1):
        stringy += str(passedlist[i]) + ', '
        # adds all except last item to str
    stringy += 'and ' + str(passedlist[len(passedlist)-1])
    # adds last item to string, after 'and'
    return stringy

Et vous pouvez gérer le cas de liste vide en:

def commacode(passedlist):
    stringy = ''
    try:
        for i in range(len(passedlist)-1):
            stringy += str(passedlist[i]) + ', '
            # adds all except last item to str
        stringy += 'and ' + str(passedlist[len(passedlist)-1])
        # adds last item to string, after 'and'
        return stringy
    except IndexError:
        return '' 
        #handles the list out of range error for an empty list by returning ''
2
toonarmycaptain 19 juil. 2017 à 04:35

Je suis un pythoniste assez nouveau. Dans la question, il a été demandé à la fonction de renvoyer le contenu de la liste sous forme de chaîne au format que les autres solutions de ce forum l'ont «imprimée». Voici (à mon avis) une solution plus propre à ce problème.

Ceci illustre la solution de code virgule du chapitre 4 [Listes] dans 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
ayaio 31 août 2017 à 13:08

Je suis nouveau sur python, il pourrait y avoir d'autres solutions plus faciles mais voici la mienne

    spam = ["cats","dogs","cows","apes"]
    def commaCode(list):
        list[-1] =  "and " + list[-1]
        print(", ".join(list))


    commaCode(spam)
-3
Salih Oztoprak 13 juin 2017 à 14:15

Juste un simple code. Je pense que nous n'avons pas besoin d'utiliser de fantaisie ici. : p

def getList(list):
    value = ''
    for i in range(len(list)):
        if i == len(list) - 1:
            value += 'and '+list[i]
        else:
            value += list[i] + ', '
    return value

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

print('### TEST ###')
print(getList(spam))
1
HenriqueAdriano 27 nov. 2018 à 22:21

Pourquoi tout le monde met des codes si complexes.

Voir mon code ci-dessous. C'est le plus simple et le plus facile à comprendre en une seule fois, même pour un débutant.

import random

def comma_code(subject):

     a = (len(list(subject)) - 1)

     for i in range(0, len(list(subject))):

          if i != a:
               print(str(subject[i]) + ', ', end="")

          else:
              print('and '+ str(subject[i]))            


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

Après avoir codé ce qui précède, tapez simplement comma_code (spam) dans le shell python et vous êtes prêt à partir. Prendre plaisir

-1
Sannidhya 19 févr. 2017 à 10:11

Voici une solution qui gère correctement la virgule Oxford. Il gère également une liste vide, auquel cas il renvoie une chaîne vide.

def list_thing(seq):
    return (' and '.join(seq) if len(seq) <= 2
        else '{}, and {}'.format(', '.join(seq[:-1]), seq[-1]))

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

for i in range(1 + len(spam)):
    seq = spam[:i]
    s = list_thing(seq)
    print(i, seq, repr(s))

sortie

0 [] ''
1 ['apples'] 'apples'
2 ['apples', 'bananas'] 'apples and bananas'
3 ['apples', 'bananas', 'tofu'] 'apples, bananas, and tofu'
4 ['apples', 'bananas', 'tofu', 'cats'] 'apples, bananas, tofu, and cats'
4
PM 2Ring 8 août 2016 à 10:25

D'autres ont donné d'excellentes solutions à une ligne, mais un bon moyen d'améliorer votre implémentation réelle - et de corriger le fait que cela ne fonctionne pas lorsque les éléments sont répétés - consiste à utiliser enumerate dans la boucle for pour garder une trace de la index, plutôt que d'utiliser index qui trouve toujours la première occurrence de la cible.

for counter, element in enumerate(list):
    new_string = new_string + str(element)
    if counter == (len(list)-2):
        ...
2
Daniel Roseman 8 août 2016 à 08:44

J'ai essayé, j'espère que c'est ce que vous cherchez: -

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

def list_thing(list):

#creating a string then splitting it as list with two items, second being last word
    new_string=', '.join(list).rsplit(',', 1)    

#Using the same method used above to recreate string by replacing the separator.

    new_string=' and'.join(new_string)
    return new_string

print(list_thing(spam))
4
PM 2Ring 8 août 2016 à 09:07

Je n'ai été satisfait d'aucune des solutions car aucune ne gère le cas avec or, par ex. apples, bananas, or berries

def oxford_comma(words, conjunction='and'):
    conjunction = ' ' + conjunction + ' '

    if len(words) <= 2:
        return conjunction.join(words)
    else:
        return '%s,%s%s' % (', '.join(words[:-1]), conjunction, words[-1])

Sinon, cette solution est plus ou moins identique à celle fournie par @ PM2Ring

0
user2426679 23 avril 2019 à 04:48

Ce code fonctionne quels que soient les types de données dans les listes, booléen, int, chaîne, flottant, 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
user3140293 13 févr. 2020 à 19:00

C'est ce que j'ai fait, IMO c'est plus intuitif ...

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

def ipso(x):
    print("'" , end="")
    def run (x):

    for i in range(len(x)):
        print(x[i]+ "" , end=',')


    run(x)
    print("'")

ipso(spam)
-1
armature hour 9 févr. 2017 à 19:46
spam=['apple', 'banana', 'tofu','cats']
spam[-1]= 'and'+' '+ spam[-1]
print (', '.join((spam)))
-2
Amunir 16 févr. 2017 à 04:08
spam=['apples','bananas','tofu','cats']
print("'",end="")
def val(some_parameter):

for i in range(0,len(spam)):
if i!=(len(spam)-1):
print(spam[i]+', ',end="")
else:
print('and '+spam[-1]+"'")
val(spam)
-1
aditi telang 24 juin 2017 à 15:28

Voici ma solution. Une fois que j'ai trouvé la méthode de jointure et comment elle a fonctionné, le reste a suivi.

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

def commas(h):
    s = ', '
    print(s.join(spam[0:len(spam)-1]) + s + 'and ' + spam[len(spam)-1])

commas(spam)
-1
Philip Horky 14 nov. 2017 à 21:38
def commacode(mylist):
    mylist[-1] = 'and ' + mylist[-1]
    mystring = ', '.join(mylist)
    return mystring

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

print commacode(spam)
-1
bojaraja 1 mai 2017 à 15:30

Pas de boucles, pas de jointures, juste deux instructions d'impression:

def commalist(listname):
    print(*listname[:-1], sep = ', ',end=", "),
    print('and',listname[-1])
0
Mike K 22 août 2019 à 15:06

Je suis venu avec cette solution

#This is the list which needs to be converted to String
spam = ['apples', 'bananas', 'tofu', 'cats']

#This is the empty string in which we will append
s = ""


def list_to_string():
    global spam,s
    for x in range(len(spam)):
        if s == "":
            s += str(spam[x])
        elif x == (len(spam)-1):
            s += " and " + str(spam[x])
        else:
            s += ", " + str(spam[x])
    return s

a = list_to_string()
print(a)
0
KshitijV97 28 janv. 2019 à 10:44