AppDividend
Latest Code Tutorials

Python zip: How to Create Iterator from Iterables in Python

The zip() is a built-in Python function that creates an iterator that will aggregate elements from two or more iterables. It takes the iterable elements like input and returns the iterator. The zip() method returns the zip object, the iterator of tuples where the first item in each passed iterator is paired together. Then the second item in each given iterator is paired together.

The zip() function takes iterables (can be zero or more), makes an iterator that aggregates items based on the iterables passed and returns the iterator of tuples.

The zip() function is the container that holds actual data inside. The zip() function returns an iterator of tuples based on the iterable objects. If the given iterators have different lengths, the iterator with the least elements determines the length of the new iterator.

The zip() is available in the built-in namespace.

If you use the dir() function to inspect __builtins__, you’ll see zip() at the end of the list.

print(dir(__builtins__))

You will see the long list, but you will find the zip last. 

If the zip python function gets no iterable items, it returns the empty iterator.

If you are using IPython, then type zip? And check what zip() is about.

If you are not using IPython, install it: “pip3 install ipython” as I use Python 3. For Python3 users, pip install ipython will be just fine.

The syntax of the zip() function in Python is the following.

zip(*iterables)

# or

zip(iterator1, iterqator2, iterator3 ...)

The zip() function takes:

iterables – can be built-in iterables (like a list, string, dict) or user-defined iterables (an object with an __iter__ method).

The zip() function returns the iterator of tuples based on an iterable object.

  1. If no parameters are passed on the zip function, zip() returns the empty iterator.
  2. If a single iterable is passed to the zip function, zip() returns the iterator of 1-tuples. Meaning, the number of items in each tuple is 1.
  3. If multiple iterables are passed, ith tuple contains ith Suppose, and two iterables are given, one iterable containing 3 and the other containing five elements. Then, a returned iterator has three tuples. It’s because the iterator stops when the shortest iterable is exhausted.

Checking zip object in Python

To check the zip object in Python, use the type() function. The type() is a built-in function that returns the Python object type. For example, if you use the zip() with n arguments, that function will return the iterator that generates tuples of length n.

#app.py

numbers = [11, 21, 46]
letters = ['e', 'k', 'a']
zipped = zip(numbers, letters)
print(type(zipped))

Output

python3 app.py
<class 'zip'>

Here, you use the zip(numbers, letters) to create the iterator that produces tuples of the form (x, y).

The x values are taken from the numbers, and the y values are taken from letters.

Notice how the Python zip() function returns the iterator. Thus, to retrieve a final list object, you need to use the list() to consume the iterator.

Passing No Arguments in Python zip()

You call zip() with no arguments, so your zipped variable holds an empty iterator. Likewise, if you consume the iterator with a list(), you’ll see an empty list.

See the following code.

# app.py

zipped = zip()
print(list(zipped))

Output

python3 app.py
[]

You could also force the empty iterator to yield an element directly. In this case, you’ll get a StopIteration exception.

# app.py

zipped = zip()
next(zipped)

Output

python3 app.py
Traceback (most recent call last):
  File "app.py", line 2, in 
    next(zipped)
StopIteration

Python tries to retrieve the next item when you call the next() on zipped. However, since zipped holds the empty iterator, there’s nothing to pull out, so Python raises the StopIteration exception.

Passing one argument

Python zip() function can take just one argument and returns an iterator that yields a series of 1-item tuples.

a = [11, 21, 19]

zippedObj = zip(a)

data = list(zippedObj)
print(data)

Output

[(11,), (21,), (19,)]

You see that the length of the resulting tuples will always equal the number of iterables you pass as arguments. Let’s give the three iterables.

a = [11, 21, 19]
b = ['hello', 'world', 'song']
c = [True, False, True]

zippedObj = zip(a, b, c)

data = list(zippedObj)
print(data)

Output

[(11, 'hello', True), (21, 'world', False), (19, 'song', True)]

You call a Python zip method with three iterables(list of strings, integers, and booleans), so the resulting tuples have three elements.

Using zip() with Python String

If you’re working with sequences like the strings, your iterables will be evaluated from left to right. So let’s define two strings, pass those in the zip() function, and see the output.

strA = 'Python'
strB = 'Go'
zippedStr = zip(strA, strB)
data = str(zippedStr)
print(data)
print(type(data))

Output

<zip object at 0x103e46940>
<class 'str'>

Using zip() with Python set

The result might be weird if you’re working with sequences like sets. For example, if there are three items in two sets. Now, you zip the list and convert the zipped object back to the list, but the values will lose their orders this time.

setA = {'x', 'y', 'z'}
setB = {11, 21, 19}
zippedObj = zip(setA, setB)
listF = list(zippedObj)
print(listF)

Output

[('y', 19), ('z', 11), ('x', 21)]

In this example, setA and setB are set objects which don’t keep their items in any particular order. Unfortunately, this means that the tuples returned by the zip() will have items that are paired up randomly.

If you’re going to use a Python zip() function with the unordered iterables like sets, this is something to consider. 

Using zip() with Python list

The zip() function takes the list like the following.

a: a1 a2 a3 a4 a5 a6 a7...
b: b1 b2 b3 b4 b5 b6 b7...
c: c1 c2 c3 c4 c5 c6 c7...

And “zip” them into one list whose entries are 3-tuples (ai, bi, ci). Imagine drawing a zipper horizontally from left to right.

Write the following code inside the app.py file.

# app.py

numList = [19, 21, 46]
strList = ['one', 'two', 'three']

outputA = zip(numList, strList)
print(list(outputA))

outputB = zip(strList, numList)
print(list(outputB))

The output is the following.

Python Zip Example

We can also convert the output to the tuple. See the following code.

# app.py

numList = [19, 21, 46]
strList = ['one', 'two', 'three']

outputA = zip(numList, strList)
print(tuple(outputA))

outputB = zip(strList, numList)
print(tuple(outputB))

The output is the following.

➜  pyt python3 app.py
((19, 'one'), (21, 'two'), (46, 'three'))
(('one', 19), ('two', 21), ('three', 46))
➜  pyt

Python zip two lists

In python 3.0, the zip method returns the zip object.

You can get a list from it by calling list(zip(a, b)).

If you want to merge lists into a list of tuples or zip two lists, you can use the zip() method. The pythonic approach is the following.

# app.py
listA = [19, 21, 46]
listB = ['one', 'two', 'three']
merge_list = zip(listA, listB)
print(list(merge_list))

See the output.

➜  pyt python3 app.py
[(19, 'one'), (21, 'two'), (46, 'three')]
➜  pyt

You must know that a zip() function stops at the end of the shortest list, which may not always be what you want in the output.

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.

Unzipping the value using zip()

We can also extract the data from the Python zip function. If we want to remove the zip, we must use the same zip()function. But we have to add an asterisk(*) in front of that list you get from the zipped variable.

We can also unzip the numList and strList. See the following example.

# app.py

numList = [19, 21, 46]
strList = ['one', 'two', 'three']

outputA = zip(numList, strList)

x, y = zip(*outputA )
print('numList = ', x)
print('strlist = ', y)

The output is the following.

➜  pyt python3 app.py
numList =  (19, 21, 46)
strlist =  ('one', 'two', 'three')
➜  pyt

The * operator can be used in conjunction with a zip to unzip the list.

You can use the list() function to get the list from the zipped variable. However, this will return several tuples. The number will differ according to the number of arguments the zip function took to zip the data.

If the passed iterators have different lengths, the iterator with the least items decides the length of the new iterator. See the following example.

# app.py

numList = [19, 21, 46, 29]
strList = ['one', 'two', 'three']

outputA = zip(numList, strList)

print(list(outputA))

The numList has four items, and strList has three elements. So the lengths are not matched. Let’s see the output.

➜  pyt python3 app.py
[(19, 'one'), (21, 'two'), (46, 'three')]
➜  pyt

Zip three iterators

Let’s take an example in which we can use three iterators and then use the zip function on it.

# app.py

numList = [19, 21, 46]
strList = ['one', 'two', 'three']
setList = {'A1', 'B1', 'C1'}

outputA = zip(numList, strList, setList)

print(list(outputA))

The output is the following.

➜  pyt python3 app.py
[(19, 'one', 'C1'), (21, 'two', 'A1'), (46, 'three', 'B1')]
➜  pyt

We took three different variables and then used the zip() function and converted it into the iterable.

Comparing Python 2 zip() with Python 3 zip()

The zip() function works differently in both versions of the Python.

In Python 2, the zip() method returns a list of tuples. The output list is truncated to the length of the shortest input iterable. If you call the zip() with no arguments, you get an empty list.

See the following code in Python2.

zipped = zip(range(3), 'WXYZ')

print(zipped)

Output

python2 app.py
[(0, 'W'), (1, 'X'), (2, 'Y')]

In this case, your call to the Python zip() method returns a list of tuples truncated at the value Z.

Now, let’s call a zip() with no arguments.

zipped = zip()

print(zipped)

Output

python2 app.py
[]

You get an empty list when you call the zip() method with no arguments. 

If you supply no arguments to zip(), the function returns an empty iterator.

zipped = zip()

print(zipped)

Output

python3 app.py
<zip object at 0x10c3a09c0>

When we give no argument to the zip() function in Python 3, you will get an empty iterator.

If you frequently use Python 2, then note that using the zip() method with long input iterables can inadvertently consume a lot of memory. In these cases, consider using the itertools.izip(*iterables) instead. This function creates the iterator that aggregates items from each of the iterables. It produces the same effect as the zip() function in Python 3. But I recommend updating the Python from 2 to 3 and using the Python 3 zip() function.

Looping Over Multiple Iterables

Python zip() function’s most use case is Looping over multiple iterables. If you need to iterate over multiple lists, tuples, or any other sequence, then it’s likely that you’ll recede on the zip(). 

Traversing Lists in Parallel

The zip() function allows us to iterate in parallel over two or more iterables. Since the zip() function generates tuples, you can unpack these in a for loop header.

dataStr = ['x', 'y', 'z']
dataInt = [11, 21, 19]

for a, b in zip(dataStr, dataInt):
    print(f'String: {a}')
    print(f'Integer: {b}')

Output

String: x
Integer: 11
String: y
Integer: 21
String: z
Integer: 19

To print the value in the console, we have formatted the string

Here, you iterate over the series of tuples returned by the zip() and unpack the elements into a and b. When you combine the zip(), for loops, and tuple unpacking, you can get a convenient and Pythonic jargon for traversing two or more iterables at once.

You can also iterate over two iterables in a single for loop. Consider the below example, which has three input iterables.

dataStr = ['x', 'y', 'z']
dataInt = [11, 21, 19]
dataSpecial = ['&', '$', '@']

for a, b, c in zip(dataStr, dataInt, dataSpecial):
    print(f'String: {a}')
    print(f'Integer: {b}')
    print(f'Special: {c}')

Output

String: x
Integer: 11
Special: &
String: y
Integer: 21
Special: $
String: z
Integer: 19
Special: @

In this example, you have used the zip() with three iterables to create and return the iterator that generates 3-item tuples. This grants us to iterate over all three iterables in one go. There are no limitations on the number of iterables you can use with Python’s zip() function.

Traversing Dictionaries in Parallel using zip()

From Python 3.6 and beyond, dictionaries are ordered collections, meaning they keep their items in the same order they were lead first. You can use the Python zip() function to iterate over multiple dictionaries safely and coherently if you leverage this aspect.

dictA = {
    'name': 'Homer',
    'age': 50,
    'type': 'fat'
}

dictB = {
    'name': 'Bart',
    'age': 10,
    'type': 'medium'
}

for (key1, val1), (key2, val2) in zip(dictA.items(), dictB.items()):
    print(key1, '->', val1)
    print(key2, '->', val2)

Output

name -> Homer
name -> Bart
age -> 50
age -> 10
type -> fat
type -> medium

Here, you iterate through dictA and dictB in parallel. In this case, zip() creates tuples with the elements from both dictionaries. Then, you can unbox each tuple and gain access to the items of both dictionaries at the same time—kids’ stuff.

You can also use the zip() function to iterate over sets in parallel. However, you’ll have to consider that, unlike dictionaries in Python 3.6, sets don’t keep their items in order. If you forget this detail, the final output of your program may not be quite what you want or expect.

Sorting in Parallel

You have to combine two lists(one is a list of ints and one is a list of strings) and sort them simultaneously. To do this, we can use zip() and the sorted() method as follows.

dataStr = ['z', 'y', 'w', 'x']
dataInt = [19, 21, 18, 46]

zippyData = zip(dataInt, dataStr)
data = list(zippyData)
print(data)
print(sorted(data))

Output

[(19, 'z'), (21, 'y'), (18, 'w'), (46, 'x')]
[(18, 'w'), (19, 'z'), (21, 'y'), (46, 'x')]

In this case, sorted() runs over the iterator generated by the zip() and sorts the items by integers, all in one go. This can be a little faster since you’ll need only two function calls: zip() and sorted().

With sorted(), you’re also writing the more general piece of code that makes sense to other programmers. For example, this will enable you to sort any sequence, not just lists.

Conclusion

In this in-depth tutorial, you’ve learned how to use Python’s zip() function. The zip() can receive multiple iterables as input and returns an iterator to create tuples with paired items from each argument. The final iterator can be helpful when you need to process the multiple iterables in the single for loop and perform some actions on their items simultaneously. That is it for this tutorial.

Recommended Posts

Python ascii()

Python bin()

Python bool()

Python any()

Python all()

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.