8. Loops and nested objects

8.1. Iterating over nested list items

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

for element in DATA:
    print(element)

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

for element in DATA:
    print(element)

# (...)
# (...)
# (...)
Code Listing 8.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')

8.2. Unpacking values in loop

Code Listing 8.4. Unpacking values in loop
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')
Code Listing 8.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
Code Listing 8.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']
Code Listing 8.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

8.3. Enumerating and item index

Code Listing 8.8. 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'),
]

i = 0

for element in DATA:
    print(f'{i} -> {element}')
    i += 1

# 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')
Code Listing 8.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, element in enumerate(DATA):
    print(f'{i} -> {element}')

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

8.4. Iterating over dict items

  • dict elements order changes!

8.4.1. Iterating over dict values

Code Listing 8.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'

8.4.2. Iterating over dict keys

Code Listing 8.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'

8.4.3. By default dict iterates over keys

Code Listing 8.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'

8.4.4. Getting pair: key, value from dict items

Code Listing 8.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

8.4.5. list of dict

Code Listing 8.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

8.5. Iterating complex types

Code Listing 8.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}"
Code Listing 8.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
Code Listing 8.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"

8.6. Assignments

8.6.1. 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: Code Listing 8.18.
  1. Mając bazę danych z listingu poniżej
  2. Iteruj po rekordach w bazie danych
  3. Z rekordu wyciągnij klucze
  4. Wypisz unikalne klucze
Code Listing 8.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'},
]
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

8.6.2. Label encoder

  • Filename: loop_label_encoder.py
  • Lines of code to write: 13 lines
  • Estimated time of completion: 15 min
  • Input data: Code Listing 8.19.
Code Listing 8.19. Sample Iris databases
[
    ('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 Code Listing 8.19. wyodrębnij dane odrzucając nagłówek

  2. Z danych wyodrębnij:

    • cechy opisujące: features: List[Tuple[float]]
    • cechy opisywane: labels: List[int]
  3. Przykład danych wyodrębnionych:

    Code Listing 8.20. Przykład danych wyodrębnionych
    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, ...]
    
  4. Aby móc odszyfrować labels i zamienić wartości na nazwy gatunków, potrzebny jest słownik podmiany “liczba -> nazwa”

  5. Wygeneruj słownik species: Dict[int, str] na podstawie danych

  6. Przykład słownika species:

    Code Listing 8.21. Przykład słownika species
    species = {
        0: 'virginica',
        1: 'setosa',
        2: 'versicolor'
    }
    
  7. Wyświetl na ekranie:

    • species
    • labels
    • features
Algorithm:
  1. Wyodrębnij dane odrzucając nagłówek
  2. Stwórz słownik gatunków species
  3. Iteruj po elementach zbioru danych
  4. Gatunek to ostatni element rekordu
  5. Jeżeli w słowniku nie ma gatunku, to dodaj go z kolejnym numerem
  6. Do listy label dodawaj wartość słownika gatunków dla gatunku w tym rekordzie
  7. Odwróć słownik gatunków
  8. Wyświetl na ekranie species oraz labels
The whys and wherefores:
 
  • Sprawdzanie występowania elementów w słowniku
  • Generowanie słownika i listy na podstawie innych danych
  • Odwracanie słownika