¿Cómo fusionar listas en una lista de tuplas?

298

¿Cuál es el enfoque pitónico para lograr lo siguiente?

# 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)]

Cada miembro de list_ces una tupla, cuyo primer miembro es de list_ay el segundo es de list_b.

Rubayeet
fuente

Respuestas:

443

En 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)]

En 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)]

fuente
77
debe saber que la función zip se detiene al final de la lista más corta, que puede no ser siempre lo que desea. el itertoolsmódulo define un zip_longest()método que se detiene al final de la lista más larga, llenando los valores faltantes con algo que proporcione como parámetro.
Adrien Plisson
55
@Adrien: saludos por su comentario aplicable. Para Python 2.x, s/zip_longest()/izip_longest(). Renombrado en Python 3.x a zip_longest().
mechanical_meat
¿podría crear [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6), etc.] usando el comando zip?
Mona Jalal
3
@MonaJalal: no, eso no es emparejarse, eso es crear el producto de las listas. itertools.product()hace eso.
Martijn Pieters
2
nota, al menos en python3.6 zip no devuelve una lista. Por lo tanto, necesita list (zip (list_a, list_b)) en su lugar
Supamee
141

En python 3.0 zip devuelve un objeto zip. Puede obtener una lista al llamar list(zip(a, b)).

Lodewijk
fuente
3
Esto puede ser trivial, pero tenga en cuenta que usar esto directamente en un bucle for le proporciona un generador que se agotará después de usarlo una vez. Guarde en una variable si desea usarla con más frecuencia
Hakaishin, el
13

Puedes usar el mapa lambda

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

Esto también funcionará si las longitudes de las listas originales no coinciden

Caballero oscuro
fuente
1
¿Por qué usar una lambda? map(None, a,b)
Padraic Cunningham
Solo tengo acceso a Python 3.5.
Dark Knight
3
Si estuviera usando python3, entonces c no sería una lista, sería un objeto de mapa, también usar una lambda será mucho menos eficiente que simplemente comprimir, si tiene listas de diferentes longitudes y desea manejar eso, entonces usaría izip_longest / zip_longest
Padraic Cunningham
8

Está buscando la función zip integrada .

Mizipzor
fuente
6

No estoy seguro de si es una forma pitónica o no, pero esto parece simple si ambas listas tienen el mismo número de elementos:

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))]
Vipin
fuente
5

Sé que esta es una vieja pregunta y ya fue respondida, pero por alguna razón, todavía quiero publicar esta solución alternativa. Sé que es fácil descubrir qué función integrada hace la "magia" que necesita, pero no está de más saber que puede hacerlo usted mismo.

>>> 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')]
Kruger
fuente
2
Cambiar una de las listas de entrada (si difieren en longitud) no es un buen efecto secundario. Además, no se necesitan las dos tareas carden el if-elif, por eso tiene el continue. (De hecho, sin el no continuetendrías que cambiar las listas: las dos tareas mencionadas anteriormente deberían mantenerse y convertirse card = (list_1[i], '')y, card = ('', list_2[1])respectivamente).
ᴠɪɴᴄᴇɴᴛ
5

El resultado que mostró en la declaración del problema no es la tupla sino la lista

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

comprobar

type(list_c)

considerando que quieres el resultado como tupla de list_a y list_b, haz

tuple(zip(list_a,list_b)) 
cyborg
fuente
Desde mi punto de vista, parece que es lo que estoy buscando y funciona bien para ambos (lista y tupla). Porque cuando usa print , verá el valor correcto (como se esperaba y mencionó @cyborg y @Lodewijk) y nada relacionado con el objeto como: <map object at 0x000001F266DCE5C0>o <zip object at 0x000002629D204C88>. Al menos, la solución sobre mapa y zip (solo) parece estar incompleta (o demasiado complicada) para mí.
Wagner_SOFC
1
La pregunta dice que quieren una lista de tuplas, no una tupla de tuplas.
goryh
1

Una alternativa sin usar zip:

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

En caso de que uno quiera obtener no solo las tuplas 1 ° con 1 °, 2 ° con 2 ° ... sino todas las combinaciones posibles de las 2 listas, eso se haría con

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
J0ANMM
fuente