6.3. Loop Nested Sequences

6.3.1. Convention

  • row - best for nested loops with sequence inside

  • Conventions for rows and columns:

    • row - row (all elements)

    • column - current column element from row sequence

    • i - row number

    • j - column number

    • x - row number

    • y - column number

    • outer - for outer loop element

    • inner - for inner loop element

  • Note that i may interfere with i used as loop counter

6.3.2. List of Pairs

>>> DATA = [('commander', 'Melissa Lewis'),
...         ('botanist', 'Mark Watney'),
...         ('chemist', 'Alex Vogel')]
>>>
>>> for pair in DATA:
...     role = pair[0]
...     name = pair[1]
...     print(f'{role} -> {name}')
commander -> Melissa Lewis
botanist -> Mark Watney
chemist -> Alex Vogel

6.3.3. List of Sequence

>>> DATA = [(5.1, 3.5, 1.4, 0.2, 'setosa'),
...         (5.7, 2.8, 4.1, 1.3, 'versicolor'),
...         (6.3, 2.9, 5.6, 1.8, 'virginica')]
>>>
>>> for row in DATA:
...     sepal_length = row[0]
...     sepal_width = row[1]
...     petal_length = row[2]
...     petal_width = row[3]
...     species = row[4]
...     total = sepal_length + sepal_width + petal_length + petal_width
...     print(f'{species} -> {total}')
setosa -> 10.2
versicolor -> 13.9
virginica -> 16.599999999999998
>>> DATA = [(5.1, 3.5, 1.4, 0.2, 'setosa'),
...         (5.7, 2.8, 4.1, 1.3, 'versicolor'),
...         (6.3, 2.9, 5.6, 1.8, 'virginica')]
>>>
>>> for row in DATA:
...     features = row[0:4]
...     label = row[4]
...     print(f'{label} -> {sum(features)}')
setosa -> 10.2
versicolor -> 13.9
virginica -> 16.599999999999998

6.3.4. Matrix

  • Suggested variable name: row

>>> DATA = [[1, 2, 3],
...         [4, 5, 6],
...         [7, 8, 9]]
>>>
>>> for row in DATA:
...     a = row[0]
...     b = row[1]
...     c = row[2]
...     print(f'{a=} {b=} {c=}')
a=1 b=2 c=3
a=4 b=5 c=6
a=7 b=8 c=9
>>> DATA = [[1, 2, 3],
...         [4, 5, 6],
...         [7, 8, 9]]
>>>
>>> for row in DATA:  # doctest: +NORMALIZE_WHITESPACE
...     print()
...
...     for value in row:
...         print(f'{value}', end=' ')
1 2 3
4 5 6
7 8 9

6.3.5. Mixed

Iterating over list with scalar and vector values - simple loop:

>>> DATA = [('Jan', 'Twardowski'), 'Watney', 69, 13.37, [True, None, False]]
>>>
>>> for obj in DATA:
...     print(obj)
('Jan', 'Twardowski')
Watney
69
13.37
[True, None, False]

Iterating over list with scalar and vector values - nested loop:

>>> DATA = [('Jan', 'Twardowski'), 'Watney', 69, 13.37, [True, None, False]]
>>>
>>> # doctest: +SKIP
... for obj in DATA:
...     for element in obj:
...         print(element)
Jan
Twardowski
W
a
t
n
e
y
Traceback (most recent call last):
TypeError: 'int' object is not iterable

Iterating over list with scalar and vector values - smart loop:

>>> DATA = [('Jan', 'Twardowski'), 'Watney', 69, 13.37, [True, None, False]]
>>>
>>> for obj in DATA:
...     if type(obj) in (list, tuple, set, frozenset):
...         for element in obj:
...             print(element)
...     else:
...         print(obj)
Jan
Twardowski
Watney
69
13.37
True
None
False

6.3.6. Assignments

Code 6.12. Solution
"""
* Assignment: Loop Nested Mean
* Complexity: easy
* Lines of code: 5 lines
* Time: 5 min

English:
    1. Use data from "Given" section (see below)
    2. Calculate mean `Sepal length` value
    3. Compare result with "Tests" section (see below)

Polish:
    1. Użyj danych z sekcji "Given" (patrz poniżej)
    2. Wylicz średnią wartość `Sepal length`
    3. Porównaj wyniki z sekcją "Tests" (patrz poniżej)

Tests:
    >>> result is not Ellipsis
    True
    >>> type(result)
    <class 'float'>
    >>> result
    5.911111111111111
"""


# Given
DATA = [('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species'),
        (5.8, 2.7, 5.1, 1.9, 'virginica'),
        (5.1, 3.5, 1.4, 0.2, 'setosa'),
        (5.7, 2.8, 4.1, 1.3, 'versicolor'),
        (6.3, 2.9, 5.6, 1.8, 'virginica'),
        (6.4, 3.2, 4.5, 1.5, 'versicolor'),
        (4.7, 3.2, 1.3, 0.2, 'setosa'),
        (7.0, 3.2, 4.7, 1.4, 'versicolor'),
        (7.6, 3.0, 6.6, 2.1, 'virginica'),
        (4.6, 3.1, 1.5, 0.2, 'setosa')]

result: float = ...


Code 6.13. Solution
"""
* Assignment: Loop Nested Unique Keys
* Complexity: medium
* Lines of code: 3 lines
* Time: 8 min

English:
    1. Use data from "Given" section (see below)
    2. Collect keys from all rows in one sequence `result`
    3. Sort `result`
    4. Print unique keys
    5. Compare result with "Tests" section (see below)

Polish:
    1. Użyj danych z sekcji "Given" (patrz poniżej)
    2. Zbierz klucze z wszystkich wierszy w jednej sekwencji `result`
    3. Posortuj `result`
    4. Wypisz unikalne klucze
    5. Porównaj wyniki z sekcją "Tests" (patrz poniżej)

Hints:
    * `row.keys()`
    * Compare solutions with :ref:`Micro-benchmarking use case`

Tests:
    >>> result is not Ellipsis
    True
    >>> type(result) in (set, list, tuple, frozenset)
    True
    >>> sorted(result)
    ['Petal length', 'Petal width', 'Sepal length', 'Sepal width', 'Species']
"""


# Given
DATA = [{'Sepal length': 5.1, 'Sepal width': 3.5, 'Species': 'setosa'},
        {'Petal length': 4.1, 'Petal width': 1.3, 'Species': 'versicolor'},
        {'Sepal length': 6.3, 'Petal width': 1.8, 'Species': 'virginica'},
        {'Sepal length': 5.0, 'Petal width': 0.2, 'Species': 'setosa'},
        {'Sepal width': 2.8, 'Petal length': 4.1, 'Species': 'versicolor'},
        {'Sepal width': 2.9, 'Petal width': 1.8, 'Species': 'virginica'}]

result = ...