364

What is the Pythonic approach to achieve the following?

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

Each member of list_c is a tuple, whose first member is from list_a and the second is from list_b.

Peter Nazarenko
  • 411
  • 1
  • 7
  • 16
rubayeet
  • 9,269
  • 8
  • 46
  • 55

10 Answers10

550

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

In 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)]
mrgloom
  • 20,061
  • 36
  • 171
  • 301
YOU
  • 120,166
  • 34
  • 186
  • 219
  • 95
    you have to know that the zip function stops at the end of the shortest list, which may not be always what you want. the `itertools` module defines a `zip_longest()` method which stops at the end of the longest list, filling missing values with something you provide as a parameter. – Adrien Plisson Mar 09 '10 at 10:05
  • 6
    @Adrien: cheers for your applicable comment. For Python 2.x, `s/zip_longest()/izip_longest()`. Renamed in Python 3.x to `zip_longest()`. – mechanical_meat Jul 10 '11 at 19:13
  • could I create [(1,5), (1,6), (1,7), (1,8), (2,5), (2,6) ,so on] using zip command? – Mona Jalal May 30 '16 at 04:39
  • 3
    @MonaJalal: no, that's not pairing up, that's creating the *product* of the lists. `itertools.product()` does that. – Martijn Pieters Aug 09 '16 at 16:12
  • 2
    note, at least in python3.6 zip does not return a list. So you need list(zip(list_a,list_b)) instead – Supamee Oct 02 '18 at 15:45
147

In python 3.0 zip returns a zip object. You can get a list out of it by calling list(zip(a, b)).

jamylak
  • 128,818
  • 30
  • 231
  • 230
Lodewijk
  • 3,741
  • 2
  • 18
  • 15
  • 4
    This might be trivial, but be warned that using this directly in a for loop gives you a generator that will be exhausted after using it once. Save into a variable if you want to use it more often – Hakaishin Sep 25 '18 at 13:34
16

You can use map lambda

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

This will also work if there lengths of original lists do not match

Dark Knight
  • 869
  • 1
  • 9
  • 18
  • 1
    Why use a lambda? `map(None, a,b)` – Padraic Cunningham Jun 08 '16 at 00:19
  • I only have have access to python 3.5. – Dark Knight Jul 13 '16 at 00:40
  • 3
    If you were using python3 then c would not be a list it would be a map object, also using a lambda is going to be a lot less efficient than just zipping, if you have different length lists and want to handle that then you would use izip_longest/zip_longest – Padraic Cunningham Aug 10 '16 at 09:09
  • it does not work when "lengths of original lists do not match". – An Se Sep 17 '20 at 08:22
  • In [56]: a = ("a","b","c","d","e") In [57]: b = (1,2,3,4,5,6,7,8,9,10) In [58]: s = list(map(lambda x,y:(x,y),a,b)) In [59]: print(s) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] No issue for me with miss matched lengths – Hutch Jun 08 '21 at 18:02
  • Hi @DarkKnight: Thank you for the solution. lambda works for me. I am thinking of creating a function by passing multiple lists/arguments in the form of `*args`. is there any dynamic way to zip multiple lists depending on different scenarios? – Xavier Sun Aug 24 '21 at 23:01
8

Youre looking for the builtin function zip.

Mizipzor
  • 51,151
  • 22
  • 97
  • 138
7

I am not sure if this a pythonic way or not but this seems simple if both lists have the same number of elements :

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))]
Jee Mok
  • 6,157
  • 8
  • 47
  • 80
Vipin
  • 99
  • 1
  • 4
6

The output which you showed in problem statement is not the tuple but list

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

check for

type(list_c)

considering you want the result as tuple out of list_a and list_b, do

tuple(zip(list_a,list_b)) 
cyborg
  • 870
  • 1
  • 15
  • 34
  • From my point of view, it seem's what I'm looking for and to work fine for the both (list and tuple). Because when you use **print**, you will see the right value (as expected and mentionned by @cyborg and @Lodewijk) and nothing related to the **object** such as : `` or ``. At least, the solution about **map** and **zip** (alone) seem's to be incomplete (or too complicated) for me. – Wagner_SOFC May 28 '17 at 01:40
  • 1
    The question states they want a list of tuples not a tuple of tuples. – goryh Jun 13 '19 at 22:41
5

I know this is an old question and was already answered, but for some reason, I still wanna post this alternative solution. I know it's easy to just find out which built-in function does the "magic" you need, but it doesn't hurt to know you can do it by yourself.

>>> 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
  • 177
  • 1
  • 4
  • 3
    Changing one of the input lists (if they differ in length) is not a nice side-effect. Also, the two assignments to `card` in the `if-elif` are not needed, that’s why you have the `continue`. (In fact, without the `continue` you wouldn’t have to change the lists: both earlier mentioned assignments should then be kept and become `card = (list_1[i], '')` and `card = ('', list_2[1])` respectively.) – ᴠɪɴᴄᴇɴᴛ Jan 07 '17 at 15:01
2

Or map with unpacking:

>>> list(map(lambda *x: x, list_a, list_b))
[(1, 5), (2, 6), (3, 7), (4, 8)]
>>> 
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
1

One alternative without using zip:

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

In case one wants to get not only tuples 1st with 1st, 2nd with 2nd... but all possible combinations of the 2 lists, that would be done with

list_d = [(p1, p2) for p1 in list_a for p2 in list_b]
J0ANMM
  • 7,849
  • 10
  • 56
  • 90
0

Like me, if anyone needs to convert it to list of lists (2D lists) instead of list of tuples, then you could do the following:

list(map(list, list(zip(list_a, list_b))))

It should return a 2D List as follows:

[[1, 5], 
 [2, 6], 
 [3, 7], 
 [4, 8]]
Sadman Sakib
  • 557
  • 3
  • 10