Comment feriez-vous une chaîne séparée par des virgules à partir d'une liste de chaînes?

529

Quelle serait votre façon préférée de concaténer des chaînes d'une séquence de telle sorte qu'entre deux paires consécutives, une virgule soit ajoutée. Autrement dit, comment mappez-vous, par exemple, ['a', 'b', 'c']à 'a,b,c'? (Les cas ['s']et []doivent être mappés respectivement à 's'et ''.)

Je finis généralement par utiliser quelque chose comme ''.join(map(lambda x: x+',',l))[:-1], mais je me sens aussi quelque peu insatisfait.

mweerden
la source

Réponses:

969
my_list = ['a', 'b', 'c', 'd']
my_string = ','.join(my_list)
'a,b,c,d'

Cela ne fonctionnera pas si la liste contient des entiers


Et si la liste contient des types autres que des chaînes (tels que des entiers, des flottants, des booléens, Aucun), procédez comme suit:

my_string = ','.join(map(str, my_list)) 
Mark Biek
la source
Notez que si vous utilisez python 2.7 (ce que vous ne devriez pas faire maintenant), l'utilisation de str lèvera une exception si l'un des éléments de la liste a unicode.
kroiz
75

Pourquoi la map/ lambdamagie? Ça ne marche pas?

>>> foo = ['a', 'b', 'c']
>>> print(','.join(foo))
a,b,c
>>> print(','.join([]))

>>> print(','.join(['a']))
a

Si la liste contient des nombres, vous pouvez utiliser la compréhension de la liste:

>>> ','.join([str(x) for x in foo])

ou une expression de générateur:

>>> ','.join(str(x) for x in foo)
jmanning2k
la source
18

",".join(l)ne fonctionnera pas dans tous les cas. Je suggère d'utiliser le module csv avec StringIO

import StringIO
import csv

l = ['list','of','["""crazy"quotes"and\'',123,'other things']

line = StringIO.StringIO()
writer = csv.writer(line)
writer.writerow(l)
csvcontent = line.getvalue()
# 'list,of,"[""""""crazy""quotes""and\'",123,other things\r\n'
Ricky
la source
Il n'y StringIOen a pas dans Python 3
Ron Kalian
4
@RonKalian Use from io import StringIOin Python 3
Kevin Ashcraft
13

Voici une solution alternative en Python 3.0 qui permet des éléments de liste non-chaîne:

>>> alist = ['a', 1, (2, 'b')]
  • une manière standard

    >>> ", ".join(map(str, alist))
    "a, 1, (2, 'b')"
  • la solution alternative

    >>> import io
    >>> s = io.StringIO()
    >>> print(*alist, file=s, sep=', ', end='')
    >>> s.getvalue()
    "a, 1, (2, 'b')"

REMARQUE: l'espace après une virgule est intentionnel.

jfs
la source
11

Ne voulez-vous pas simplement:

",".join(l)

Évidemment, cela devient plus compliqué si vous devez citer / échapper des virgules, etc. dans les valeurs. Dans ce cas, je suggère de regarder le module csv dans la bibliothèque standard:

https://docs.python.org/library/csv.html

Douglas Leeder
la source
10

@Peter Hoffmann

L'utilisation d'expressions de générateur a également l'avantage de produire un itérateur, mais économise l'importation d'itertools. De plus, les compréhensions de liste sont généralement préférées à mapper, donc je m'attends à ce que les expressions de générateur soient préférées à imap.

>>> l = [1, "foo", 4 ,"bar"]
>>> ",".join(str(bit) for bit in l)
'1,foo,4,bar' 
Aaron Maenpaa
la source
7
>>> my_list = ['A', '', '', 'D', 'E',]
>>> ",".join([str(i) for i in my_list if i])
'A,D,E'

my_listpeut contenir tout type de variables. Cela évite le résultat 'A,,,D,E'.

Shameem
la source
4
l=['a', 1, 'b', 2]

print str(l)[1:-1]

Output: "'a', 1, 'b', 2"
AlvaroAV
la source
1
Je pense que vous devez souligner que contrairement aux autres solutions de cette page, vous citez également des chaînes.
mrdevlar
3

@ jmanning2k utilisant une compréhension de liste a l'inconvénient de créer une nouvelle liste temporaire. La meilleure solution serait d'utiliser itertools.imap qui retourne un itérateur

from itertools import imap
l = [1, "foo", 4 ,"bar"]
",".join(imap(str, l))
Peter Hoffmann
la source
Cette solution ne remplit pas les conditions de ne pas ajouter de virgule supplémentaire pour une chaîne vide et d'ajouter un «Aucun» avec NoneType.
Roberto
vérifier le str.join travail plus rapidement par listrapport au générateur
Grijesh Chauhan
3

Voici un exemple avec liste

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

Plus précise:-

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [type(i) == list and i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

Exemple 2: -

myList = ['Apple','Orange']
myList = ','.join(map(str, myList)) 
print "Output:", myList
Output: Apple,Orange

la source
1
Cette question concernait les listes, pas les listes de listes .
Eero Aaltonen
@EeroAaltonen J'ai mis à jour ma réponse, merci de me pointer vers la droite.
1

Je dirais csv bibliothèque est la seule option raisonnable ici, car elle a été conçue pour faire face à tous les cas d'utilisation csv tels que les virgules dans une chaîne, etc.

Pour sortir une liste ldans un fichier .csv:

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(l)  # this will output l as a single row.  

Il est également possible d'utiliser writer.writerows(iterable) pour sortir plusieurs lignes vers csv.

Cet exemple est compatible avec Python 3, car l'autre réponse utilisée ici StringIOest Python 2.

Ron Kalian
la source
Mais n'est-ce pas trop / compliqué par rapport aux autres réponses?
Sreenikethan I
0

À moins que je manque quelque chose, ','.join(foo)je dois faire ce que vous demandez.

>>> ','.join([''])
''
>>> ','.join(['s'])
's'
>>> ','.join(['a','b','c'])
'a,b,c'

(modifier: et comme le souligne jmanning2k,

','.join([str(x) for x in foo])

est plus sûr et assez Pythonique, bien que la chaîne résultante soit difficile à analyser si les éléments peuvent contenir des virgules - à ce stade, vous avez besoin de la pleine puissance du csvmodule, comme Douglas le souligne dans sa réponse.)

David Singer
la source
-2

Mes deux centimes. J'aime plus simple un code d'une ligne en python:

>>> from itertools import imap, ifilter
>>> l = ['a', '', 'b', 1, None]
>>> ','.join(imap(str, ifilter(lambda x: x, l)))
a,b,1
>>> m = ['a', '', None]
>>> ','.join(imap(str, ifilter(lambda x: x, m)))
'a'

C'est pythonique, fonctionne pour les chaînes, les nombres, Aucun et la chaîne vide. Il est court et répond aux exigences. Si la liste ne contient pas de nombres, nous pouvons utiliser cette variante plus simple:

>>> ','.join(ifilter(lambda x: x, l))

De plus, cette solution ne crée pas de nouvelle liste, mais utilise un itérateur, comme l'a souligné @Peter Hoffmann (merci).

Roberto
la source
C'est superflu. La réponse acceptée est simple, directe et clairement la meilleure solution. Fournir des alternatives trop complexes est une perte de temps inutile. Si vous essayez simplement d'éduquer sur d'autres caractéristiques de la langue alors qu'il existe déjà des réponses viables, vous faites la même chose pour laquelle vous m'avez rétrogradé.
clearlight