Mathematics, Sciences, and Technologies

Python for Scientists 2-4: More on Iterables

,

Definition of Iterables

In general, iterables in Python are objects that can be iterated over, i.e. elements inside can be taken out of it one at a time. Lists, tuples, dictionaries, sets, and range (but not limited to these) are all iterables. Furthermore, an iterator is a closely related object equipped with the necessary corresponding methods, particularly next to retrieve the next entry. The aforementioned lists, tuples, dictionaries, sets, and range are not iterators by themselves and require the function iter to wrap them. (However, iterators are always iterable.) We now demonstrate this below:

my_iter = iter(["parsley", "sage", "rosemary", "thyme"])
print(next(my_list))
print(next(my_list))
print(next(my_list))
print(next(my_list))
print(next(my_list))

This produces

parsley
sage
rosemary
thyme
Traceback (most recent call last):
File "c:\Users\user\Downloads\test.py", line 9, in <module>
print(next(my_list))
~~~~^^^^^^^^^
StopIteration

The first four next calls take the elements one by one in order. And when all of them have been exhausted, it returns an error indicating this. It can be used in for loops just like other iterables:

my_iter = iter(["parsley", "sage", "rosemary", "thyme"])
for flower in my_iter:
print("Get me a", flower, "!")

resulting in

Get me a parsley !
Get me a sage !
Get me a rosemary !
Get me a thyme !

Enumerate

The enumerate function can be applied to any iterable and returns an iterator that runs through the elements inside the original iterable, but also with an index that comes before each, and they are paired in tuples. Let’s try to expand the above example:

my_iter_enum = enumerate(my_iter)
print(next(my_iter_enum))
print(next(my_iter_enum))
print(next(my_iter_enum))
print(next(my_iter_enum))

This will give

(0, 'parsley')
(1, 'sage')
(2, 'rosemary')
(3, 'thyme')

This can also be supplied to a for loop. Since now each entry generated by the new enumerate object is a tuple with two components, we may explicitly expand (unpack) them by using two dummy variables in the for loop as well:

for index, flower in enumerate(my_iter):
print(f"Item {index+1}: {flower}.")

The dummy index/flower assumes the first/second component returned by enumerate, and outputs

Item 1: parsley.
Item 2: sage.
Item 3: rosemary.
Item 4: thyme.

Zip

When there are multiple iterables to be processed in parallel within a for loop, the zip function will pack them component by component into an iterator. To illustrate, we can write

colors = ["red", "yellow", "green", "blue"]
shapes = ["circle", "square", "triangle", "star"]
for color, shape in zip(colors, shapes):
print(f"Here is a {color} {shape}.")

which gives

Here is a red circle.
Here is a yellow square.
Here is a green triangle.
Here is a blue star.

This is the most convenient when used along with a dictionary (see this tutorial), and let’s recall the keys and values method:

cities_latlon = {"Beijing": (39.9, 116.4), "London": (51.5, 0.1), "Los Angeles": (34.1, -118.2)}
for city, latlon in zip(cities_latlon.keys(), cities_latlon.values()):
print(f"{city} is located at {latlon}.")

This produces

Beijing is located at (39.9, 116.4).
London is located at (51.5, 0.1).
Los Angeles is located at (34.1, -118.2).

Note that zip can be applied to more than two iterables and the readers may try to play around that.

Exercise

Given

unit_types = ["mage", "warrior", "hunter", "mage"]
lvs = [53, 48, 51, 44]

print the following outputs

Unit 1: Level 53 mage
Unit 2: Level 48 warrior
Unit 3: Level 51 hunter
Unit 4: Level 44 mage

You will need to combine zip and enumerate, and there are multiple ways to do it. You can select the first/second item in a zipped object by the usual indexing [0], [1].

Suggested Solution

A possible way is via

for index, stat in enumerate(zip(unit_types, lvs)):
print(f"Unit {index+1}: Level {stat[1]} {stat[0]}")

However, a better approach involves “unpacking”, which will be further discussed in a future post:

for index, (unit, lv) in enumerate(zip(unit_types, lvs)):
print(f"Unit {index+1}: Level {lv} {unit}")

Leave a Reply

I’m Benjamin

Welcome to my Mathematical World! Here you can find posts and tutorials related to applied topics like Linear Algebra, Calculus, Differential Equations, and Programming. Feel free to leave comments and suggestions!