7. Iterating nested sequences

7.1. Iterating over nested list items

Listing 24. Iterating over nested list items
DATA = [1, 2, 3]

for obj in DATA:
    print(obj)

# 1
# 2
# 3
Listing 25. Iterating over nested list items
DATA = [(...), (...), (...)]

for obj in DATA:
    print(obj)

# (...)
# (...)
# (...)
Listing 26. Iterating over nested list items
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:
    print(row)

# (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')

7.2. Unpacking values in loop

7.2.1. Recap information about unpacking

Listing 27. Unpacking values
a, b = 1, 2
a, b = (1, 2)
k, v = (1, 2)
key, value = (1, 2)

7.2.2. Unpacking list of pairs

Listing 28. Unpacking values in loop
DATA = [
    ('a', 1),
    ('b', 2),
    ('c', 3),
]

for key, value in DATA:
    print(f'{key} -> {value}')

# a -> 1
# b -> 2
# c -> 3
Listing 29. Unpacking values in loop
DATA = [
    (1, 2),
    ('name', 'Jan Twardowski'),
    ('species', ['setosa', 'versicolor', 'virginica']),
    ((1, 2), ['Johnson Space Center', 'Kennedy Space Center']),
]

for key, value in DATA:
    print(f'{key} -> {value}')

# 1 -> 2
# name -> Jan Twardowski
# species -> ['setosa', 'versicolor', 'virginica']
# (1, 2) -> ['Johnson Space Center', 'Kennedy Space Center']

7.2.3. Unpacking list of sequences

Listing 30. Unpacking values in loop
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'),
]

# sepal_len, sepal_wid, petal_len, petal_wid, species = (5.1, 3.5, 1.4, 0.2, 'setosa')

for sepal_len, sepal_wid, petal_len, petal_wid, species in DATA:
    print(f'{species} -> {sepal_len}')

# setosa -> 5.1
# versicolor -> 5.7
# virginica -> 6.3

7.2.4. list of dict

Listing 31. list of dict
DATA = [
    {'Sepal length': 5.1, 'Sepal width': 3.5, 'Petal length': 1.4, 'Petal width': 0.2, 'Species': 'setosa'},
    {'Sepal length': 5.7, 'Sepal width': 2.8, 'Petal length': 4.1, 'Petal width': 1.3, 'Species': 'versicolor'},
    {'Sepal length': 6.3, 'Sepal width': 2.9, 'Petal length': 5.6, 'Petal width': 1.8, 'Species': 'virginica'},
]

for row in DATA:
    sepal_length = row['Sepal length']
    species = row['Species']
    print(f'{species} -> {sepal_length}')

# setosa -> 5.1
# versicolor -> 5.7
# virginica -> 6.3

7.3. Enumerating and item index

Listing 32. Enumerating and item index
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 i, row in enumerate(DATA):
    print(f'{i} -> {row}')

# 0 -> (5.1, 3.5, 1.4, 0.2, 'setosa')
# 1 -> (5.7, 2.8, 4.1, 1.3, 'versicolor')
# 2 -> (6.3, 2.9, 5.6, 1.8, 'virginica')

7.4. Iterating complex types

Listing 33. Iterating over list with scalar and vector values - simple loop
DATA = [('Jan', 'Twardowski'), 'Watney', 42, 13.37, {True, None, False}]

for element in DATA:
    print(element})

# ('Jan', 'Twardowski')
# Watney
# 42
# 13.37
# {False, True, None}
Listing 34. Iterating over list with scalar and vector values - nested loop
DATA = [('Jan', 'Twardowski'), 'Watney', 42, 13.37, {True, None, False}]

for outer in DATA:
    for inner in outer:
        print(inner)

# Jan
# Twardowski
# W
# a
# t
# n
# e
# y
# Traceback (most recent call last):
#   File "<input>", line 4, in <module>
# TypeError: 'int' object is not iterable
Listing 35. Iterating over list with scalar and vector values - smart loop
DATA = [('Jan', 'Twardowski'), 'Watney', 42, 13.37, {True, None, False}]


for outer in DATA:
    if isinstance(outer, (list, set, tuple))
        for inner in outer:
            print(inner)
    else:
        print(outer)

# Jan
# Twardowski
# Watney
# 42
# 13.37
# False
# True
# None

7.5. Assignments

7.5.1. Get elements from nested data structure

  • Complexity level: easy

  • Lines of code to write: 3 lines

  • Estimated time of completion: 10 min

  • Filename: solution/for_nested.py

English
  1. For input data (see below)

  2. Separate header from data

  3. Iterate over data

  4. Print species names ending with "ca" or "sa"

Polish
  1. Dla danych wejściowych (patrz poniżej)

  2. Oddziel nagłówek od danych

  3. Iteruj po danych

  4. Wypisz nazwy gatunków kończące się na "ca" lub "sa"

Input
INPUT = [
    ('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'}),
]
The whys and wherefores
  • Accessing dict keys

  • Iterating over nested structure

7.5.2. Unique keys from schema-less database

English
  1. For input data (see below)

  2. Collect unique keys in one sequence

  3. Print the sequence

Polish
  1. Dla danych wejściowych (patrz poniżej)

  2. Zbierz unikalne klucze w jednej sekwencji

  3. Wypisz sekwencję

Input
INPUT = [
    {'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'},
    {'Petal length': 1.4, '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'},
]
The whys and wherefores
  • Generating set

  • Deduplication

  • Accessing dict keys

  • Iterating over nested structure

  • Updating set

Hint

7.5.3. Label encoder

English
  1. For input data (see below)

  2. Define:

    • features: List[Tuple[float]] - measurements

    • labels: List[int] - species

  3. Separate header from data

  4. To encode and decode labels (species) we need label_encoder: Dict[int, str]:

    • key - id (incremented integer value)

    • value - species name

  5. label_encoder must be generated from INPUT

  6. For each row add appropriate data to features, labels and label_encoder

  7. Print features, labels and label_encoder

  8. Output must be identical to output data (see below)

Polish
  1. Dla danych wejściowych (patrz poniżej)

  2. Zdefiniuj:

    • features: List[Tuple[float]] - pomiary

    • labels: List[int] - gatunki

    • label_encoder: Dict[int, str] - słownik podmiany nazw gatunków

  3. Odseparuj nagłówek od danych

  4. Aby móc zakodować i odkodować labels (gatunki) potrzebny jest label_encoder: Dict[int, str]:

    • key - identyfikator (kolejna liczba rzeczywista)

    • value - nazwa gatunku

  5. label_encoder musi być wygenerowany z INPUT

  6. Dla każdego wiersza dodawaj odpowiednie dane do feature, labels i label_encoder

  7. Wypisz feature, labels i label_encoder

  8. Wynik ma być identyczny z danymi wyjściowymi (patrz poniżej)

Input
INPUT = [
    ('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.9, 3.0, 1.4, 0.2, 'setosa'),
    (4.9, 2.5, 4.5, 1.7, 'virginica'),
    (7.1, 3.0, 5.9, 2.1, 'virginica'),
    (4.6, 3.4, 1.4, 0.3, 'setosa'),
    (5.4, 3.9, 1.7, 0.4, 'setosa'),
    (5.7, 2.8, 4.5, 1.3, 'versicolor'),
    (5.0, 3.6, 1.4, 0.3, 'setosa'),
    (5.5, 2.3, 4.0, 1.3, 'versicolor'),
    (6.5, 3.0, 5.8, 2.2, 'virginica'),
    (6.5, 2.8, 4.6, 1.5, 'versicolor'),
    (6.3, 3.3, 6.0, 2.5, 'virginica'),
    (6.9, 3.1, 4.9, 1.5, 'versicolor'),
    (4.6, 3.1, 1.5, 0.2, 'setosa'),
]
Output
features = [
    (5.8, 2.7, 5.1, 1.9),
    (5.1, 3.5, 1.4, 0.2),
    (5.7, 2.8, 4.1, 1.3),
    (6.3, 2.9, 5.6, 1.8),
    (6.4, 3.2, 4.5, 1.5),
    (4.7, 3.2, 1.3, 0.2), ...]

labels = [0, 1, 2, 1, 2, 0, ...]

label_encoder = {
    0: 'virginica',
    1: 'setosa',
    2: 'versicolor'}
The whys and wherefores
  • dict lookups

  • Dynamic dict generating

  • dict reversal