Comment fusionner des listes en une liste de tuples?


298

Quelle est l'approche Pythonic pour atteindre les objectifs suivants?

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

Chaque membre de list_cest un tuple, dont le premier membre est de list_aet le second est de list_b.

Réponses:


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

77
vous devez savoir que la fonction zip s'arrête à la fin de la liste la plus courte, ce qui n'est pas toujours ce que vous voulez. le itertoolsmodule définit une zip_longest()méthode qui s'arrête à la fin de la liste la plus longue, remplissant les valeurs manquantes avec quelque chose que vous fournissez comme paramètre.
Adrien Plisson

5
@Adrien: bravo pour votre commentaire applicable. Pour Python 2.x, s/zip_longest()/izip_longest(). Renommé en Python 3.x en zip_longest().
mechanical_meat

puis-je créer [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6), etc.] à l'aide de la commande zip?
Mona Jalal

3
@MonaJalal: non, ce n'est pas l'appariement, c'est la création du produit des listes. itertools.product()est-ce que.
Martijn Pieters

2
note, au moins en python3.6 zip ne renvoie pas de liste. Vous avez donc besoin de list (zip (list_a, list_b)) à la place
Supamee

141

En python 3.0, zip renvoie un objet zip. Vous pouvez en obtenir une liste en appelant list(zip(a, b)).


3
Cela peut être trivial, mais sachez que l'utiliser directement dans une boucle for vous donne un générateur qui sera épuisé après l'avoir utilisé une fois. Enregistrez dans une variable si vous souhaitez l'utiliser plus souvent
Hakaishin

13

Vous pouvez utiliser la carte lambda

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

Cela fonctionnera également si la longueur des listes originales ne correspond pas


1
Pourquoi utiliser un lambda? map(None, a,b)
Padraic Cunningham

Je n'ai accès qu'à python 3.5.
Dark Knight

3
Si vous utilisiez python3, alors c ne serait pas une liste, ce serait un objet de carte.Utiliser également un lambda sera beaucoup moins efficace que de simplement zipper, si vous avez des listes de longueurs différentes et que vous souhaitez gérer cela, vous utiliserez izip_longest / zip_longest
Padraic Cunningham


6

Je ne sais pas si c'est une manière pythonique ou pas mais cela semble simple si les deux listes ont le même nombre d'éléments:

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

Je sais que c'est une vieille question à laquelle on a déjà répondu, mais pour une raison quelconque, je veux toujours publier cette solution alternative. Je sais qu'il est facile de découvrir quelle fonction intégrée fait la "magie" dont vous avez besoin, mais cela ne fait pas de mal de savoir que vous pouvez le faire vous-même.

>>> 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
Changer une des listes d'entrée (si elles diffèrent en longueur) n'est pas un bon effet secondaire. De plus, les deux affectations carddans le if-elifne sont pas nécessaires, c'est pourquoi vous avez le continue. (En fait, sans que continuevous n'auriez pas à modifier les listes: les deux missions mentionnées précédemment devraient alors être conservés et deviennent card = (list_1[i], '')et card = ('', list_2[1])respectivement.)
ᴠɪɴᴄᴇɴᴛ

5

La sortie que vous avez montrée dans l'énoncé du problème n'est pas le tuple mais la liste

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

vérifier

type(list_c)

considérant que vous voulez que le résultat soit un tuple de list_a et list_b, faites

tuple(zip(list_a,list_b)) 

De mon point de vue, cela semble être ce que je recherche et fonctionne bien pour les deux (liste et tuple). Parce que lorsque vous utilisez l' impression , vous verrez la bonne valeur (comme prévu et mentionné par @cyborg et @Lodewijk) et rien lié à l' objet tel que: <map object at 0x000001F266DCE5C0>ou <zip object at 0x000002629D204C88>. Au moins, la solution concernant la carte et le zip (seul) semble être incomplète (ou trop compliquée) pour moi.
Wagner_SOFC

1
La question indique qu'ils veulent une liste de tuples et non un tuple de tuples.
goryh

1

Une alternative sans utiliser zip:

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

Dans le cas où l'on veut obtenir non seulement des tuples 1er au 1er, 2e au 2e ... mais toutes les combinaisons possibles des 2 listes, cela se ferait avec

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.