Como mesclar listas em uma lista de tuplas?

298

Qual é a abordagem pitônica para obter o seguinte?

# 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 membro de list_cé uma tupla, cujo primeiro membro é de list_ae o segundo é de list_b.

rubayeet
fonte

Respostas:

443

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

No 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)]
VOCÊ
fonte
77
você precisa saber que a função zip para no final da lista mais curta, o que pode não ser sempre o que você deseja. o itertoolsmódulo define um zip_longest()método que para no final da lista mais longa, preenchendo os valores ausentes com algo que você fornece como parâmetro.
Adrien Plisson
5
@ Adrien: felicidades pelo seu comentário aplicável. Para Python 2.x s/zip_longest()/izip_longest(),. Renomeado em Python 3.x para zip_longest().
Mechanical_meat
eu poderia criar [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6), etc.] usando o comando zip?
Mona Jalal
3
@MonaJalal: não, isso não está emparelhado, está criando o produto das listas. itertools.product()faz isso.
Martijn Pieters
2
note que pelo menos no python3.6 zip não retorna uma lista. Então você precisa list (zip (list_a, list_b)) em vez disso
Supamee
141

No python 3.0, zip retorna um objeto zip. Você pode obter uma lista dela ligando list(zip(a, b)).

Lodewijk
fonte
3
Isso pode ser trivial, mas lembre-se de que o uso direto em um loop for fornece um gerador que será esgotado após o uso uma vez. Salve em uma variável se você quiser usá-lo com mais freqüência
Hakaishin
13

Você pode usar o mapa lambda

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

Isso também funcionará se os comprimentos das listas originais não corresponderem

Cavaleiro das Trevas
fonte
1
Por que usar um lambda? map(None, a,b)
Padraic Cunningham
Eu só tenho acesso ao python 3.5.
Dark Knight
3
Se você estivesse usando python3, então c não seria uma lista, seria um objeto de mapa, também usar um lambda será muito menos eficiente do que apenas compactar, se você tiver listas de tamanhos diferentes e quiser lidar com isso, usaria izip_longest / zip_longest
Padraic Cunningham
8

Você está procurando o zip da função embutida .

Mizipzor
fonte
6

Não tenho certeza se isso é uma maneira python ou não, mas isso parece simples se ambas as listas tiverem o mesmo 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
fonte
5

Sei que essa é uma pergunta antiga e já foi respondida, mas, por algum motivo, ainda quero postar esta solução alternativa. Eu sei que é fácil descobrir qual função interna faz a "mágica" que você precisa, mas não faz mal saber que você pode fazer isso sozinho.

>>> 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
fonte
2
Alterar uma das listas de entrada (se elas diferirem em tamanho) não é um bom efeito colateral. Além disso, as duas atribuições para cardno if-elifnão são necessárias, é por isso que você tem o continue. (Na verdade, sem o continueque não teria de alterar as listas: ambas as atribuições anteriormente mencionados devem ser mantidos e tornar-se card = (list_1[i], '')e card = ('', list_2[1]), respectivamente.)
ᴠɪɴᴄᴇɴᴛ
5

A saída que você mostrou na declaração do problema não é a tupla, mas a lista

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

verificar se há

type(list_c)

considerando que você deseja o resultado como tupla fora de list_a e list_b, faça

tuple(zip(list_a,list_b)) 
cyborg
fonte
Do meu ponto de vista, parece que estou procurando e que funcione bem para ambos (lista e tupla). Porque ao usar a impressão , você verá o valor certo (conforme o esperado e mencionado por @cyborg e @Lodewijk) e nada relacionado ao objeto , como: <map object at 0x000001F266DCE5C0>ou <zip object at 0x000002629D204C88>. Pelo menos, a solução sobre map e zip (sozinha) parece estar incompleta (ou muito complicada) para mim.
Wagner_SOFC
1
A pergunta indica que eles querem uma lista de tuplas e não uma tupla.
goryh
1

Uma alternativa sem usar zip:

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

Caso você queira obter não apenas as tuplas 1ª com 1ª, 2ª com 2ª ... mas todas as combinações possíveis das 2 listas, isso seria feito com

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