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.

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

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


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ą


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


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

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

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

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]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.