2015-05-06 25 views
25

Sto provando a trasformare una lista in stringhe separate unite con una e commerciale se ci sono solo due voci, o virgole e una e commerciale tra le ultime due ad es.Come unire l'elenco in Python ma rendere l'ultimo separatore diverso?

Jones & Ben 
Jim, Jack & James 

Al momento ho questo:

pa = ' & '.join(listauthors[search]) 

e non sanno come fare a risolvere il problema virgola/commerciale. Principiante quindi sarebbe gradita una spiegazione completa.

risposta

18
"&".join([",".join(my_list[:-1]),my_list[-1]]) 

penserei avrebbe funzionato

o forse solo

",".join(my_list[:-1]) +"&"+my_list[-1] 

per gestire casi limite in cui solo 2 elementi si potrebbe

"&".join([",".join(my_list[:-1]),my_list[-1]] if len(my_list) > 2 else my_list) 
13

Si potrebbe rompere questo in due join. Unire tutto tranne l'ultimo articolo con ", ". Quindi unisci questa stringa e l'ultimo elemento con " & ".

all_but_last = ', '.join(authors[:-1]) 
last = authors[-1] 

' & '.join([all_but_last, last]) 

Nota: Questo non riguarda casi limite, ad esempio quando authors è vuoto o ha un solo elemento.

3

È possibile prima aderire l'tutti i nomi con virgola e utilizzare espressioni regolari per sostituire l'ultima virgola:

>>> import re 
>>> l=['Jim','Jack','James','Zahra','Kasra'] 
>>> re.sub(r', (\w+)$',r'& \1',' , '.join(l)) 
'Jim , Jack , James , Zahra & Kasra' 
3
('{}, '*(len(authors)-2) + '{} & '*(len(authors)>1) + '{}').format(*authors) 

Questa soluzione in grado di gestire un elenco di autori di lunghezza> 0, anche se può essere modificato per gestire anche liste di lunghezza 0. L'idea è di creare prima una stringa di formato che possiamo formattare dalla lista di disimballaggio. Questa soluzione evita di affettare l'elenco in modo che dovrebbe essere abbastanza efficiente per grandi elenchi di autori.

Per prima cosa concateniamo '{}, ' per ogni autore aggiuntivo oltre a due autori. Quindi concateniamo '{} & ' se ci sono due o più autori. Infine aggiungiamo '{}' per l'ultimo autore, ma questa sottoespressione può essere '{}'*(len(authors)>0) se vogliamo essere in grado di gestire una lista vuota di autori. Infine, formiamo la stringa completata disimballando gli elementi dell'elenco utilizzando la sintassi di decompressione *.

Se non è necessario un solo liner, questo è il codice in una funzione efficiente.

def format_authors(authors): 
    n = len(authors) 
    if n > 1: 
     return ('{}, '*(n-2) + '{} & {}').format(*authors) 
    elif n > 0: 
     return authors[0] 
    else: 
     return '' 

Questo può gestire un elenco di autori di qualsiasi lunghezza.

+0

mi piace! Non ho pensato di provare solo con una stringa di formattazione. Non sono sicuro che avrei saputo da dove cominciare. –

+2

@DougR. Bene, l'idea è di sedersi e pensare alle formule matematiche. Vogliamo solo la e commerciale se la lunghezza degli autori è maggiore di 1. Vogliamo solo 1 separatore di virgola per ogni autore maggiore di 2. È grazioso perché ''anystring' * 0' è solo la stringa vuota. – Shashank

+0

Ho un'altra domanda. Questo metodo può essere adattato per inserire una virgola prima della e commerciale per un elenco di lunghezza * n *, dove * n> 2 *? Io, "Jim, ** Jack, ** e John." Questo non viene chiesto come un "pasticcio", ma come una domanda genuina, come la maggior parte dei manuali di stile americano lo impongono. Francamente, non vedo un modo per farlo senza girare 'if n> 1: ...' in 'if n> 2: .../elif n> 1: ...', e ciò sembra sbagliato in qualche modo a fare una soluzione così elegante. Grazie! –

2

Sembra che mentre stavo lavorando alla mia risposta, qualcuno potrebbe aver picchiato me al pugno con uno simile. Ecco il mio per il confronto. Si noti che questo gestisce anche casi di 0, 1 o 2 membri nell'elenco.

# Python 3.x, should also work with Python 2.x. 
def my_join(my_list): 
    x = len(my_list) 
    if x > 2: 
     s = ', & '.join([', '.join(my_list[:-1]), my_list[-1]]) 
    elif x == 2: 
     s = ' & '.join(my_list) 
    elif x == 1: 
     s = my_list[0] 
    else: 
     s = '' 
    return s 

assert my_join(['Jim', 'Jack', 'John']) == 'Jim, Jack, & John' 
assert my_join(['Jim', 'Jack']) == 'Jim & Jack' 
assert my_join(['Jim',]) == 'Jim' 
assert my_join([]) == '' 
6

Una fodera. Basta concatenare tutto tranne l'ultimo elemento con , come delimitatore. Quindi aggiungi semplicemente & e infine l'ultimo elemento alla fine.

print ', '.join(lst[:-1]) + ' & ' + lst[-1] 

Se si desidera gestire liste vuote o tali:

if len(lst) > 1: 
    print ', '.join(lst[:-1]) + ' & ' + lst[-1] 
elif len(lst) == 1: 
    print lst[0] 
Problemi correlati