11. Loops

11.1. while

  • Continue execution when argument is True
while True:
    pass
i = 0

while i <= 10:
    print(i)
    i += 1

11.2. for

11.2.1. Iterating over str

  • Iterating str will get character on each iteration:

    for character in 'Hello':
        print(character)
    
    # H
    # e
    # l
    # l
    # o
    

11.2.2. Iterating simple collections

  • Iterating over list:

    DATA = [1, 2.5, 'Jose Jimenez']
    
    for element in DATA:
        print(element)
    
    # 1
    # 2.5
    # 'Jose Jimenez'
    
  • Iterating over tuple:

    DATA = (1, 2.5, 'Jose Jimenez')
    
    for element in DATA:
        print(element)
    
    # 1
    # 2.5
    # 'Jose Jimenez'
    
  • range(0, 5) will generate (0, 1, 2, 3, 4)

    for number in range(0, 5):
        print(f'Value is: {number}')
    
    # Value is: 0
    # Value is: 1
    # Value is: 2
    # Value is: 3
    # Value is: 4
    

11.2.3. Iterating over nested list items

DATA = [
    ('a', 0),
    ('b', 1),
    ('c', 2),
]

for element in DATA:
    print(element)

# ('a', 0)
# ('b', 1)
# ('c', 2)
a, b = 'a', 0
a, b = ('a', 0)
key, value = ('a', 0)
DATA = [
    ('a', 0),
    ('b', 1),
    ('c', 2),
]

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

# key: "a", value: "0"
# key: "b", value: "1"
# key: "c", value: "2"
DATA = [
    (0, 1),
    ('name', 'José'),
    ('locations', ['CapeCanaveral', 'Houston']),
]

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

# key: "0",         value: "1"
# key: "name",      value: "José"
# key: "locations", value: "['CapeCanaveral', 'Houston']"

11.2.4. enumerate()

DATA = ['a', 'b', 'c']

for element in DATA:
    print(element)
# a
# b
# c
DATA = ['a', 'b', 'c']

for index, element in enumerate(DATA):
    print(index, element)
# 0 a
# 1 b
# 2 c

11.2.5. Iterating over dict items

  • dict elements order changes!

  • Iterating over dict values:

    DATA = {
        'first_name': 'José',
        'last_name': 'Jiménez',
        'age': 42,
    }
    
    DATA.values()
    # ['José', 'Jiménez', 42]
    
    for element in DATA.values():
        print(element)
    
    # 'José'
    # 'Jiménez'
    # 42
    
  • Iterating over dict keys:

    DATA = {
        'first_name': 'José',
        'last_name': 'Jiménez',
        'age': 42,
    }
    
    my_dict.keys()
    # ['first_name', 'last_name', 'age']
    
    for element in DATA.keys():
        print(element)
    
    # 'first_name'
    # 'last_name'
    # 'age'
    
  • By default dict iterates over keys:

    DATA = {
        'first_name': 'José',
        'last_name': 'Jiménez',
        'age': 42,
    }
    
    for element in DATA:
        print(element)
    
    # 'first_name'
    # 'last_name'
    # 'age'
    
  • Getting pair: key, value from dict items:

    DATA = {
        'first_name': 'José',
        'last_name': 'Jiménez',
        'age': 42,
    }
    
    DATA.items()
    # [('first_name', 'José'), ('last_name', 'Jiménez'), ('age', 42)]
    
    for key, value in DATA.items():
        print(f'key: "{key}", value: "{value}"')
    
    # key: "first_name", value: "José"
    # key: "last_name",  value: "Jiménez"
    # key: "age",        value: "42"
    

11.2.6. Iterating complex types

  • flatmap
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}"
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
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"

11.3. Assignments

11.3.1. Text manipulation

  1. Dany jest tekst przemównienia John F. Kennedy’ego “Moon Speech” wygłoszony na Rice Stadium (zdania oddzielone są kropkami)

    We choose to go to the Moon. We choose to go to the Moon in this decade and do the other things. Not because they are easy, but because they are hard. Because that goal will serve to organize and measure the best of our energies and skills. Because that challenge is one that we are willing to accept. One we are unwilling to postpone. And one we intend to win
    
  2. Policz ile jest wyrazów w każdym zdaniu

  3. Wypisz na ekranie listę słowników (List[Dict[str, int]]) o strukturze:

    • klucz: zdanie
    • wartość: ilość wyrazów
  4. Na końcu wypisz także ile jest:

    • zdań
    • słów
    • znaków
About:
  • Filename: loop_sentences.py
  • Lines of code to write: 10 lines
  • Estimated time of completion: 10 min
Co zadanie sprawdza:
 
  • Dzielenie stringów
  • Sprawdzanie długości ciągów znaków
  • Iterowanie po elementach listy

11.3.2. Unique keys from schema-less database

  1. Mając bazę danych z listingu poniżej
  2. Wygeneruj listę unikalnych kluczy dictów
DATABASE = [
    {'last_name': 'Jiménez'},
    {'first_name': 'Mark', 'last_name': 'Watney'},
    {'first_name': 'Иван', 'age': 42},
    {'first_name': 'Matt', 'last_name': 'Kowalski', 'born': 1961},
    {'first_name': 'José', 'born': 1961, 'agency': 'NASA'},
]
Algorithm:
  1. Iteruj po rekordach w bazie danych
  2. Z rekordu wyciągnij klucze
  3. Dodaj klucze do zbioru
  4. Usuń duplikaty w zbiorze
About:
  • Filename: loop_unique_keys.py
  • Lines of code to write: 5 lines
  • Estimated time of completion: 10 min
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

11.3.3. Label encoder

  1. Dany jest zbiór pomiarów Irysów Code Listing 11.1.

  2. Ze zbioru wyodrębnij dane odrzucając nagłówek

  3. Z danych wyodrębnij:

    • cechy opisujące: features: List[Tuple[float]]
    • cechy opisywane: labels: List[int]
  4. 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, ...]
    
  5. Aby móc odszyfrować labels i zamienić wartości na nazwy gatunków, potrzebny jest słownik podmiany “liczba -> nazwa”

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

  7. Przykład słownika species:

    species = {
        0: 'virginica',
        1: 'setosa',
        2: 'versicolor'
    }
    
  8. 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
About:
  • Filename: loop_label_encoder.py
  • Lines of code to write: 13 lines
  • Estimated time of completion: 15 min
The whys and wherefores:
 
  • Sprawdzanie występowania elementów w słowniku
  • Generowanie słownika i listy na podstawie innych danych
  • Odwracanie słownika
Code Listing 11.1. 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'),
]