6. Iterating nested sequences

6.1. Iterating over nested list items

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

for element in DATA:
    print(element)

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

for element in DATA:
    print(element)

# (...)
# (...)
# (...)
Listing 28. 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 29. 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 30. 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 31. 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 32. 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 33. 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 34. 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 35. 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 36. 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 37. 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 38. 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 39. 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 40. 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 41. 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 42. 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. Get elements from nested data structure

  1. Na podstawie DATA z Listing 43.

  2. Po odrzuceniu nagłówka iteruj po danych

  3. Wyświetl na ekranie nazwy gatunków zaczynające się na "v".

Listing 43. Iris sample dataset
DATA = [
    ('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species'),
    (5.8, 2.7, 5.1, 1.9, {'species': 'virginica'}),
    (5.1, 3.5, 1.4, 0.2, {'species': 'setosa'}),
    (5.7, 2.8, 4.1, 1.3, {'species': 'versicolor'}),
    (6.3, 2.9, 5.6, 1.8, {'species': 'virginica'}),
    (6.4, 3.2, 4.5, 1.5, {'species': 'versicolor'}),
    (4.7, 3.2, 1.3, 0.2, {'species': 'setosa'}),
    (7.0, 3.2, 4.7, 1.4, {'species': 'versicolor'}),
    (7.6, 3.0, 6.6, 2.1, {'species': 'virginica'}),
    (4.6, 3.1, 1.5, 0.2, {'species': 'setosa'}),
]

6.6.2. dict to dict

  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.3. Unique keys from schema-less database

Listing 44. 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 44.

  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.4. Label encoder

Listing 45. 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 45. 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 46. 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