Come unire gli elenchi in un elenco di tuple?


298

Qual è l'approccio Pythonic per ottenere quanto segue?

# Original lists:

list_a = [1, 2, 3, 4]
list_b = [5, 6, 7, 8]

# List of tuples from 'list_a' and 'list_b':

list_c = [(1,5), (2,6), (3,7), (4,8)]

Ogni membro di list_cè una tupla, il cui primo membro proviene list_ae il secondo viene da list_b.

Risposte:


443

In Python 2:

>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> zip(list_a, list_b)
[(1, 5), (2, 6), (3, 7), (4, 8)]

In Python 3:

>>> list_a = [1, 2, 3, 4]
>>> list_b = [5, 6, 7, 8]
>>> list(zip(list_a, list_b))
[(1, 5), (2, 6), (3, 7), (4, 8)]

77
devi sapere che la funzione zip si ferma alla fine dell'elenco più breve, che potrebbe non essere sempre quello che vuoi. il itertoolsmodulo definisce un zip_longest()metodo che si arresta alla fine dell'elenco più lungo, riempiendo i valori mancanti con qualcosa fornito come parametro.
Adrien Plisson,

5
@Adrien: saluti per il tuo commento applicabile. Per Python 2.x, s/zip_longest()/izip_longest(). Rinominato in Python 3.x a zip_longest().
Mechanical_meat

potrei creare [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6), ecc.] usando il comando zip?
Mona Jalal,

3
@MonaJalal: no, non si sta accoppiando, sta creando il prodotto delle liste. itertools.product()fa quello.
Martijn Pieters

2
nota, almeno in python3.6 zip non restituisce un elenco. Quindi hai bisogno di list (zip (list_a, list_b)) invece
Supamee

141

In python 3.0 zip restituisce un oggetto zip. È possibile ottenere un elenco da esso chiamando list(zip(a, b)).


3
Questo potrebbe essere banale, ma tieni presente che l'uso diretto in un ciclo for ti dà un generatore che si esaurirà dopo averlo usato una volta. Salva in una variabile se vuoi usarla più spesso
Hakaishin,

13

Puoi usare la mappa lambda

a = [2,3,4]
b = [5,6,7]
c = map(lambda x,y:(x,y),a,b)

Questo funzionerà anche se le lunghezze degli elenchi originali non corrispondono


1
Perché usare un lambda? map(None, a,b)
Padraic Cunningham,

Ho solo accesso a Python 3.5.
Dark Knight,

3
Se stavi usando python3, allora c non sarebbe un elenco, sarebbe un oggetto mappa, anche l'uso di un lambda sarà molto meno efficiente del semplice zippare, se hai elenchi di lunghezze diverse e vuoi gestirlo, allora useresti izip_longest / zip_longest
Padraic Cunningham


6

Non sono sicuro se questo sia un modo pitonico o no, ma questo sembra semplice se entrambe le liste hanno lo stesso numero di elementi:

list_a = [1, 2, 3, 4]

list_b = [5, 6, 7, 8]

list_c=[(list_a[i],list_b[i]) for i in range(0,len(list_a))]

5

So che questa è una vecchia domanda a cui è già stata data una risposta, ma per qualche ragione, voglio ancora pubblicare questa soluzione alternativa. So che è facile scoprire quale funzione integrata fa la "magia" di cui hai bisogno, ma non fa male sapere che puoi farlo da solo.

>>> list_1 = ['Ace', 'King']
>>> list_2 = ['Spades', 'Clubs', 'Diamonds']
>>> deck = []
>>> for i in range(max((len(list_1),len(list_2)))):
        while True:
            try:
                card = (list_1[i],list_2[i])
            except IndexError:
                if len(list_1)>len(list_2):
                    list_2.append('')
                    card = (list_1[i],list_2[i])
                elif len(list_1)<len(list_2):
                    list_1.append('')
                    card = (list_1[i], list_2[i])
                continue
            deck.append(card)
            break
>>>
>>> #and the result should be:
>>> print deck
>>> [('Ace', 'Spades'), ('King', 'Clubs'), ('', 'Diamonds')]

2
La modifica di uno degli elenchi di input (se differiscono in lunghezza) non è un buon effetto collaterale. Inoltre, i due compiti di cardin if-elifnon sono necessari, ecco perché hai il continue. (In effetti, senza il non continuedovresti cambiare gli elenchi: entrambi i compiti precedentemente menzionati dovrebbero quindi essere mantenuti e diventare card = (list_1[i], '')e card = ('', list_2[1])rispettivamente.)
ᴠɪɴᴄᴇɴᴛ

5

L'output mostrato nell'istruzione del problema non è la tupla ma l'elenco

list_c = [(1,5), (2,6), (3,7), (4,8)]

controlla

type(list_c)

considerando che si desidera ottenere il risultato come tupla da list_a e list_b, fare

tuple(zip(list_a,list_b)) 

Dal mio punto di vista, sembra sia quello che sto cercando e di lavorare bene per entrambi (elenco e tupla). Perché quando usi la stampa , vedrai il giusto valore (come previsto e menzionato da @cyborg e @Lodewijk) e niente correlato all'oggetto come: <map object at 0x000001F266DCE5C0>o <zip object at 0x000002629D204C88>. Almeno, la soluzione su map e zip (da sola) sembra essere incompleta (o troppo complicata) per me.
Wagner_SOFC,

1
La domanda afferma che vogliono un elenco di tuple, non una tupla di tuple.
Goryh,

1

Un'alternativa senza usare zip:

list_c = [(p1, p2) for idx1, p1 in enumerate(list_a) for idx2, p2 in enumerate(list_b) if idx1==idx2]

Nel caso in cui si desideri ottenere non solo tuple 1a con 1a, 2a con 2a ... ma tutte le possibili combinazioni delle 2 liste, che si farebbe con

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.