Jak połączyć listy w listę krotek?

297

Jakie jest podejście Python do osiągnięcia następujących celów?

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

Każdy członek list_cjest krotką, której pierwszy członek jest z, list_aa drugi jest z list_b.

rubayeet
źródło

Odpowiedzi:

442

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

W Pythonie 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)]
TY
źródło
77
musisz wiedzieć, że funkcja zip zatrzymuje się na końcu najkrótszej listy, co może nie zawsze być tym, czego chcesz. itertoolsmoduł definiuje zip_longest()metodę, która zatrzymuje się na końcu najdłuższej listy, wypełnianie brakujących wartości, z czymś, co zapewni jako parametr.
Adrien Plisson
5
@Adrien: kibicuje za odpowiedni komentarz. Dla Pythona 2.x, s/zip_longest()/izip_longest(). Zmieniono nazwę w Python 3.x na zip_longest().
Mechanical_meat
czy mogę utworzyć [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6) itd.] za pomocą polecenia zip?
Mona Jalal
3
@MonaJalal: nie, to nie jest parowanie, to tworzenie iloczynu list. itertools.product()robi to.
Martijn Pieters
2
Uwaga, przynajmniej w python3.6 zip nie zwraca listy. Więc zamiast tego potrzebujesz listy (zip (list_a, list_b))
Supamee
141

W Pythonie 3.0 zip zwraca obiekt zip. Możesz uzyskać listę, dzwoniąc list(zip(a, b)).

Lodewijk
źródło
3
Może to być trywialne, ale należy pamiętać, że użycie tego bezpośrednio w pętli for daje generator, który zostanie wyczerpany po jednorazowym użyciu. Zapisz w zmiennej, jeśli chcesz jej częściej używać
Hakaishin,
13

Możesz użyć mapy lambda

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

Będzie to również działać, jeśli długości oryginalnych list się nie zgadzają

Mroczny rycerz
źródło
1
Dlaczego warto korzystać z lambda? map(None, a,b)
Padraic Cunningham
Mam tylko dostęp do Pythona 3.5.
Dark Knight
3
Jeśli używasz Python3, to c nie byłoby listą, to byłby obiekt mapy, również użycie lambda będzie o wiele mniej wydajne niż zwykłe kompresowanie, jeśli masz listy o różnych długościach i chcesz sobie z tym poradzić, wtedy użyjesz izip_longest / zip_longest
Padraic Cunningham
8

Szukasz wbudowanej funkcji zip .

Mizipzor
źródło
6

Nie jestem pewien, czy jest to pythonowy sposób, czy nie, ale wydaje się to proste, jeśli obie listy mają tę samą liczbę elementów:

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
źródło
5

Wiem, że to stare pytanie, na które już udzielono odpowiedzi, ale z jakiegoś powodu nadal chcę opublikować to alternatywne rozwiązanie. Wiem, że łatwo jest po prostu dowiedzieć się, która wbudowana funkcja wykonuje „magię”, której potrzebujesz, ale nie szkodzi, że możesz to zrobić samodzielnie.

>>> 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
źródło
2
Zmiana jednej z list wejściowych (jeśli różnią się długością) nie jest przyjemnym efektem ubocznym. Ponadto dwa przypisania do cardw if-elifnie są potrzebne, dlatego masz continue. (W rzeczywistości, bez continuenie musiałby zmienić wykazy: oba wcześniej wymienione zadania powinny być utrzymane, a następnie stać card = (list_1[i], '')i card = ('', list_2[1])odpowiednio.)
ᴠɪɴᴄᴇɴᴛ
5

Dane wyjściowe pokazane w opisie problemu nie są krotką, lecz listą

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

Sprawdź

type(list_c)

biorąc pod uwagę, że chcesz wynik jako krotkę z list_a i list_b, zrób

tuple(zip(list_a,list_b)) 
cyborg
źródło
Z mojego punktu widzenia wydaje mi się, że tego właśnie szukam i działa dobrze dla obu (listy i krotki). Ponieważ kiedy używasz print , zobaczysz właściwą wartość (zgodnie z oczekiwaniami i wzmianką o @cyborg i @Lodewijk) i nic związanego z obiektem, takie jak: <map object at 0x000001F266DCE5C0>lub <zip object at 0x000002629D204C88>. Przynajmniej rozwiązanie dotyczące mapy i zip (sam) wydaje mi się niekompletne (lub zbyt skomplikowane) dla mnie.
Wagner_SOFC
1
Pytanie brzmi: chcą listy krotek, a nie krotek krotek.
goryh
1

Jedna alternatywa bez użycia zip:

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

W przypadku, gdy chce się uzyskać nie tylko krotki 1. z 1., 2. z 2.… ale wszystkie możliwe kombinacje 2 list, to można zrobić z

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
J0ANMM
źródło