6. Iterating nested sequences

6.1. Iterating over nested list items

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

for element in DATA:
    print(element)

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

for element in DATA:
    print(element)

# (...)
# (...)
# (...)
Listing 6.3. 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 element in DATA:
    print(element)

# (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.2. Unpacking values in loop

Listing 6.4. Unpacking values
a, b = 'a', 0
a, b = ('a', 0)
k, v = ('a', 0)
key, value = ('a', 0)

sepal_len, sepal_wid, petal_len, petal_wid, species = (5.1, 3.5, 1.4, 0.2, 'setosa')
*measurements, species = (5.1, 3.5, 1.4, 0.2, 'setosa')
Listing 6.5. Unpacking values in loop
DATA = [
    ('a', 0),
    ('b', 1),
    ('c', 2),
]

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

# a -> 0
# b -> 1
# c -> 2
Listing 6.6. Unpacking values in loop
DATA = [
    (0, 1),
    ('name', 'José'),
    ('locations', ['CapeCanaveral', 'Houston']),
]

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

# 0 -> 1
# name -> José
# locations -> ['CapeCanaveral', 'Houston']
Listing 6.7. 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(species)

# setosa
# versicolor
# virginica
Listing 6.8. 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'),
]

for *measurements, species in DATA:
    print(f'{species} -> {measurements}')

# setosa -> [5.1, 3.5, 1.4, 0.2]
# versicolor -> [5.7, 2.8, 4.1, 1.3]
# virginica -> [6.3, 2.9, 5.6, 1.8]

6.3. Enumerating and item index

Listing 6.9. 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')

6.4. Iterating over dict items

  • Since Python 3.7 dict has of adding elements

  • Before Python 3.7 dict order is not ensured!!

6.4.1. Iterating over dict values

Listing 6.10. Iterating over dict items
DATA = {
    'Sepal length': 5.1,
    'Sepal width': 3.5,
    'Petal length': 1.4,
    'Petal width': 0.2,
    'Species': 'setosa',
}

DATA.values()
# [5.1, 3.5, 1.4, 0.2, 'setosa']

for element in DATA.values():
    print(element)

# 5.1
# 3.5
# 1.4
# 0.2
# 'setosa'

6.4.2. Iterating over dict keys

Listing 6.11. Iterating over dict items
DATA = {
    'Sepal length': 5.1,
    'Sepal width': 3.5,
    'Petal length': 1.4,
    'Petal width': 0.2,
    'Species': 'setosa',
}

DATA.keys()
# ['Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species']

for element in DATA.keys():
    print(element)

# 'Sepal length'
# 'Sepal width'
# 'Petal length'
# 'Petal width'
# 'Species'

6.4.3. By default dict iterates over keys

Listing 6.12. By default dict iterates over keys
DATA = {
    'Sepal length': 5.1,
    'Sepal width': 3.5,
    'Petal length': 1.4,
    'Petal width': 0.2,
    'Species': 'setosa',
}

for element in DATA:
    print(element)

# 'Sepal length'
# 'Sepal width'
# 'Petal length'
# 'Petal width'
# 'Species'

6.4.4. Getting pair: key, value from dict items

Listing 6.13. Getting pair: key, value from dict items
DATA = {
    'Sepal length': 5.1,
    'Sepal width': 3.5,
    'Petal length': 1.4,
    'Petal width': 0.2,
    'Species': 'setosa',
}

DATA.items()
# [
#   ('Sepal length', 5.1),
#   ('Sepal width', 3.5),
#   ('Petal length', 1.4),
#   ('Petal width', 0.2),
#   ('Species', 'setosa')
# ]


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

# Sepal length -> 5.1
# Sepal width -> 3.5
# Petal length -> 1.4
# Petal width -> 0.2
# Species -> setosa

6.4.5. list of dict

Listing 6.14. 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:
    print(row['Species'])

# setosa
# versicolor
# virginica

6.5. Iterating complex types

Listing 6.15. Iterating over list with scalar and vector values - simple loop
DATA = ['Max', ('1.0', 'José'), 3, 2.8, {True, None, False}]

for element in DATA:
    print(f'value: "{element}"')

# value: "Max"
# value: "('1.0', 'José')"
# value: "3"
# value: "2.8"
# value: "{False, True, None}"
Listing 6.16. Iterating over list with scalar and vector values - nested loop
DATA = ['Max', ('1.0', 'José'), 3, 2.8, {True, None, False}]

for element in DATA:
    for sub in element:
        print(f'value: "{sub}"')

# value: "M"
# value: "a"
# value: "x"
# value: "1.0"
# value: "José"
# TypeError: 'int' object is not iterable
Listing 6.17. Iterating over list with scalar and vector values - smart loop
DATA = ['Max', ('1.0', 'José'), 3, 2.8, {True, None, False}]

for element in DATA:

    if isinstance(element, (list, set, tuple)):
        for sub in element:
            print(f'value: "{sub}"')
    else:
        print(f'value: "{element}"')

# value: "Max"
# value: "1.0"
# value: "José"
# value: "3"
# value: "2.8"
# value: "False"
# value: "True"
# value: "None"

6.6. Assignments

6.6.1. dict to dict

  • Filename: for_dict_to_dict.py

  • Lines of code to write: 4 lines

  • Estimated time of completion: 10 min

  1. Dany jest dict w formacie:

    DATA = {
        6: ['Doctorate', 'Prof-school'],
        5: ['Masters', 'Bachelor', 'Engineer'],
        4: ['HS-grad'],
        3: ['Junior High'],
        2: ['Primary School'],
        1: ['Kindergarten'],
    }
    
  2. Przekonwertuj go aby uzyskać format:

    output = {
        'Doctorate': '6',
        'Prof-school': '6',
        'Masters': '5',
        'Bachelor': '5',
        'Engineer': '5',
        'HS-grad': '4',
        'Junior High': '3',
        'Primary School': '2',
        'Kindergarten': '1'
    }
    
The whys and wherefores
  • Wyciąganie elementów ze słownika

  • Iterowanie po słowniku

  • Aktualizacja słownika

6.6.2. Unique keys from schema-less database

  • Filename: loop_unique_keys.py

  • Lines of code to write: 5 lines

  • Estimated time of completion: 5 min

  • Input data: Listing 6.18.

Listing 6.18. Unique keys from schema-less database
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'},
    {'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'},
]
  1. Mając bazę danych z listingu Listing 6.18.

  2. Iteruj po rekordach w bazie danych

  3. Z rekordu wyciągnij klucze

  4. Wypisz unikalne klucze

The whys and wherefores
  • Generowanie zbiorów

  • Usuwanie powtarzających się elementów

  • Wyciąganie elementów ze słownika

  • Iterowanie po słowniku

  • Aktualizacja zbiorów

Hint

6.6.3. Label encoder

  • Filename: loop_label_encoder.py

  • Lines of code to write: 13 lines

  • Estimated time of completion: 15 min

  • Input data: Listing 6.19.

Listing 6.19. Sample Iris databases
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.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'),
]
  1. Ze zbioru Listing 6.19. wyodrębnij dane

  2. Zdefiniuj:

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

    • y: List[int] - labels - gatunki

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

  3. Aby móc odszyfrować labels i zamienić wartości int na nazwy gatunków (str), potrzebny jest słownik podmiany “liczba -> nazwa gatunku”. Na podstawie danych (nie zapisuj go na sztywno w kodzie) wygeneruj taki słownik

  4. Dla każdego rekordu wyodrębnij pomiary i nazwę gatunku

  5. Zaktualizuj odpowiednie listy

  6. Wyświetl na ekranie X, y i label_encoder:

  7. Efekt końcowy:

    Listing 6.20. Przykład danych wyodrębnionych
    X = [
        (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), ...]
    
    y = [0, 1, 2, 1, 2, 0, ...]
    
    label_encoder = {
        0: 'virginica',
        1: 'setosa',
        2: 'versicolor'}
    
The whys and wherefores
  • Sprawdzanie występowania elementów w słowniku

  • Generowanie słownika i listy na podstawie innych danych

  • Odwracanie słownika