4.8. Idiom Map¶
Map (convert) elements in sequence
Generator (lazy evaluated)
map(callable, *iterables)
required
callable
- Functionrequired
iterables
- 1 or many sequence or iterator objects
>>> from inspect import isgeneratorfunction, isgenerator
>>>
>>>
>>> isgeneratorfunction(map)
False
>>>
>>> result = map(float, [1,2,3])
>>> isgenerator(result)
False
4.8.1. Example¶
>>> result = (float(x) for x in range(0,5))
>>>
>>> list(result)
[0.0, 1.0, 2.0, 3.0, 4.0]
>>> result = map(float, range(0,5))
>>>
>>> list(result)
[0.0, 1.0, 2.0, 3.0, 4.0]
4.8.2. Problem¶
>>> data = [1, 2, 3]
>>> result = []
>>>
>>> for x in data:
... result.append(float(x))
>>>
>>> print(result)
[1.0, 2.0, 3.0]
4.8.3. Solution¶
>>> data = [1, 2, 3]
>>> result = map(float, data)
>>>
>>> list(result)
[1.0, 2.0, 3.0]
4.8.4. Lazy Evaluation¶
>>> data = [1, 2, 3]
>>> result = map(float, data)
>>>
>>> next(result)
1.0
>>> next(result)
2.0
>>> next(result)
3.0
>>> next(result)
Traceback (most recent call last):
StopIteration
4.8.5. Multi Parameters¶
>>> def myfunc(x):
... return sum(x)
>>>
>>>
>>> DATA = [
... (1,2),
... (3,4),
... ]
>>>
>>> result = map(myfunc, DATA)
>>> print(list(result))
[3, 7]
4.8.6. Starmap¶
>>> from itertools import starmap
>>>
>>>
>>> DATA = [
... (3.1415, 3),
... (2.71828, 2),
... ]
>>>
>>> result = starmap(round, DATA) # round(number=3.1415, ndigits=2)
>>> print(list(result))
[3.142, 2.72]
4.8.7. Partial¶
>>> from functools import partial
>>>
>>>
>>> round1 = partial(round, ndigits=1)
>>> DATA = [1.111, 2.222, 3.333]
>>>
>>> result = map(round1, DATA) # round(number=1.111, ndigits=1)
>>> print(list(result))
[1.1, 2.2, 3.3]
4.8.8. Performance¶
>>> def even(x):
... return x % 2 == 0
>>>
... %%timeit -r 1000 -n 1000
... result = [float(x) for x in data if even(x)]
1.9 µs ± 206 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>>
... %%timeit -r 1000 -n 1000
... result = list(map(float, filter(parzysta, data)))
1.66 µs ± 175 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
4.8.9. Use Case - 0x01¶
Built-in functions:
>>> DATA = [1, 2, 3]
>>> result = map(float, DATA)
>>>
>>> tuple(map(float, DATA))
(1.0, 2.0, 3.0)
>>> DATA = [1, 2, 3]
>>> result = map(float, DATA)
>>>
>>> set(map(float, DATA))
{1.0, 2.0, 3.0}
>>> DATA = [1, 2, 3]
>>> result = (float(x) for x in DATA)
>>>
>>> list(result)
[1.0, 2.0, 3.0]
>>> DATA = [1.1, 2.2, 3.3]
>>> result = map(round, DATA)
>>>
>>> list(result)
[1, 2, 3]
4.8.10. Use Case - 0x02¶
>>> def square(x):
... return x ** 2
>>>
>>>
>>> DATA = [1, 2, 3]
>>> result = map(square, DATA)
>>>
>>> list(result)
[1, 4, 9]
4.8.11. Use Case - 0x03¶
>>> def increment(x):
... return x + 1
>>>
>>>
>>> DATA = [1, 2, 3, 4]
>>> result = map(increment, DATA)
>>>
>>> list(result)
[2, 3, 4, 5]
4.8.12. Use Case - 0x04¶
>>> def translate(letter):
... return PL.get(letter, letter)
>>>
>>>
>>> DATA = 'zażółć gęślą jaźń'
>>> PL = {'ą': 'a', 'ć': 'c', 'ę': 'e',
... 'ł': 'l', 'ń': 'n', 'ó': 'o',
... 'ś': 's', 'ż': 'z', 'ź': 'z'}
>>>
>>> result = map(translate, DATA)
>>> ''.join(result)
'zazolc gesla jazn'
4.8.13. Use Case - 0x05¶
Standard input:
>>> import sys
>>>
>>>
... print(sum(map(int, sys.stdin)))
$ cat ~/.profile |grep addnum
alias addnum='python -c"import sys; print(sum(map(int, sys.stdin)))"'
4.8.14. Use Case - 0x06¶
>>> import requests
>>>
>>> url = 'https://python3.info/_static/iris-dirty.csv'
>>>
>>> data = requests.get(url).text
>>> header, *rows = data.splitlines()
>>> nrows, nfeatures, *class_labels = header.strip().split(',')
>>> label_encoder = dict(enumerate(class_labels))
>>> result = []
>>> for row in rows:
... *features, species = row.strip().split(',')
... features = map(float, features)
... species = label_encoder[int(species)]
... row = tuple(features) + (species,)
... result.append(row)
>>> def decode(row):
... *features, species = row.strip().split(',')
... features = map(float, features)
... species = label_encoder[int(species)]
... return tuple(features) + (species,)
>>>
>>> result = map(decode, rows)
>>> def decode(row):
... *features, species = row.strip().split(',')
... features = map(float, features)
... species = label_encoder[int(species)]
... return tuple(features) + (species,)
>>>
>>> with open('/tmp/myfile.csv') as file:
... header = file.readline()
... for line in map(decode, file):
... print(line)
4.8.15. Use Case - 0x07¶
SetUp:
>>> from doctest import testmod as run_tests
Data [1]:
>>> DATA = """150,4,setosa,versicolor,virginica
... 5.1,3.5,1.4,0.2,0
... 7.0,3.2,4.7,1.4,1
... 6.3,3.3,6.0,2.5,2
... 4.9,3.0,1.4,0.2,0
... 6.4,3.2,4.5,1.5,1
... 5.8,2.7,5.1,1.9,2"""
Definition:
>>> def get_labelencoder(header: str) -> dict[int, str]:
... """
... >>> get_labelencoder('150,4,setosa,versicolor,virginica')
... {0: 'setosa', 1: 'versicolor', 2: 'virginica'}
... """
... nrows, nfeatures, *class_labels = header.split(',')
... return dict(enumerate(class_labels))
>>>
>>> run_tests()
TestResults(failed=0, attempted=1)
>>> def get_data(line: str) -> tuple:
... """
... >>> convert('5.1,3.5,1.4,0.2,0')
... (5.1, 3.5, 1.4, 0.2, 'setosa')
... >>> convert('7.0,3.2,4.7,1.4,1')
... (7.0, 3.2, 4.7, 1.4, 'versicolor')
... >>> convert('6.3,3.3,6.0,2.5,2')
... (6.3, 3.3, 6.0, 2.5, 'virginica')
... """
... *values, species = line.split(',')
... values = map(float, values)
... species = label_encoder[int(species)]
... return tuple(values) + (species,)
>>>
>>> run_tests()
TestResults(failed=0, attempted=3)
>>> header, *lines = DATA.splitlines()
>>> label_encoder = get_labelencoder(header)
>>> result = map(get_data, lines)
>>> list(result)
[(5.1, 3.5, 1.4, 0.2, 'setosa'),
(7.0, 3.2, 4.7, 1.4, 'versicolor'),
(6.3, 3.3, 6.0, 2.5, 'virginica'),
(4.9, 3.0, 1.4, 0.2, 'setosa'),
(6.4, 3.2, 4.5, 1.5, 'versicolor'),
(5.8, 2.7, 5.1, 1.9, 'virginica')]
4.8.16. Use Case - 0x08¶
>>>
... import pandas as pd
...
...
... DATA = 'https://python3.info/_static/phones-pl.csv'
...
... result = (
... pd
... .read_csv(DATA, parse_dates=['datetime'])
... .set_index('datetime', drop=True)
... .drop(columns=['id'])
... .loc['2000-01-01':'2000-03-01']
... .query('item == "sms"')
... .groupby(['period','item'])
... .agg(
... duration_count = ('duration', 'count'),
... duration_sum = ('duration', 'sum'),
... duration_median = ('duration', 'median'),
... duration_mean = ('duration', 'mean'),
... duration_std = ('duration', 'std'),
... duration_var = ('duration', 'var'),
... value = ('duration', lambda column: column.mean().astype(int))
... )
... )
4.8.17. Use Case - 0x09¶
>>> from functools import reduce
>>> from operator import add
>>>
>>>
>>> def even(x):
... return x % 2 == 0
>>>
>>> def positive(x):
... return x > 0
>>>
>>> def non_negative(x):
... return x >= 0
>>>
>>> def square(x):
... return x ** 2
>>>
>>> def add1(x):
... return x + 1
>>>
>>> def minus1(x):
... return x + 1
>>> data = range(0, 1024)
>>> data = filter(even, data)
>>> data = filter(positive, data)
>>> data = filter(non_negative, data)
>>> data = map(square, data)
>>> data = map(add1, data)
>>> data = map(minus1, data)
>>> result = reduce(add, data)
>>>
>>> result
178434046
>>> filters = [
... even,
... positive,
... non_negative,
... ]
>>>
>>> maps = [
... square,
... add1,
... minus1,
... ]
>>>
>>> def apply(data, fn):
... return map(fn, data)
>>>
>>>
>>> data = range(0, 1024)
>>> data = reduce(apply, filters, data)
>>> data = reduce(apply, maps, data)
>>> result = reduce(add, data)
>>>
>>> result
3072
4.8.18. References¶
4.8.19. Assignments¶
"""
* Assignment: Idiom Map Apply
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 2 min
English:
1. Define function `cube()`:
a. takes one argument
b. returns its argument cubed (raised to the power of 3)
2. Use `map()` to apply function `cube()` to DATA
3. Define `result: map` with result
4. Run doctests - all must succeed
Polish:
1. Zdefiniuj funckję `cube()`:
a. przyjmuje jeden argument
b. zwraca argument podniesiony do sześcianu (do 3 potęgi)
2. Użyj `map()` aby zaaplikować funkcję `cube()` do DATA
3. Zdefiniuj `result: map` z wynikiem
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* map()
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> assert isfunction(cube), \
'Object `cube` must be a function'
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Evaluated `result` has invalid type, should be list'
>>> assert all(type(x) is int for x in result), \
'All rows in `result` should be int'
>>> result
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
"""
DATA = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Returns its argument cubed (raised to the power of 3)
# type: Callable[[int], [int]]
def cube(x):
...
# Cube numbers in DATA
# type: map
result = ...
"""
* Assignment: Idiom Map Apply
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 3 min
English:
1. Define function `upper()`:
a. takes one argument (str)
b. returns argument uppercased
2. Use `map()` to apply function `upper()` to DATA
3. Define `result: map` with result
4. Run doctests - all must succeed
Polish:
1. Zdefiniuj funckję `upper()`:
a. przyjmuje jeden argument (str)
b. zwraca argument dużymi literami
2. Użyj `map()` aby zaaplikować funkcję `upper()` do DATA
3. Zdefiniuj `result: map` z wynikiem
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* map()
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> assert isfunction(upper), \
'Object `upper` must be a function'
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Evaluated `result` has invalid type, should be list'
>>> assert all(type(x) is str for x in result), \
'All rows in `result` should be str'
>>> result
['A', 'B', 'C']
"""
DATA = ['a', 'b', 'c']
# Define function `upper()`:
# - takes one argument (str)
# - returns argument uppercased
# type: Callable[[str], [str]]
def upper():
...
# Use `map()` to apply function `upper()` to DATA
# type: map
result = ...
"""
* Assignment: Idiom Map Apply
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min
English:
1. Use `map()` to apply function `str.upper()` to DATA
2. Do not define own function
3. Define `result: map` with result
4. Run doctests - all must succeed
Polish:
1. Użyj `map()` aby zaaplikować funkcję `str.upper()` do DATA
2. Nie definiuj własnej funkcji
3. Zdefiniuj `result: map` z wynikiem
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* map()
* str.upper()
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Evaluated `result` has invalid type, should be list'
>>> assert all(type(x) is str for x in result), \
'All rows in `result` should be str'
>>> result
['A', 'B', 'C']
"""
DATA = ['a', 'b', 'c']
# Use `map()` to apply function `str.upper()` to DATA
# type: map
result = ...
"""
* Assignment: Datetime ISO List
* Complexity: medium
* Lines of code: 1 lines
* Time: 2 min
English:
1. Define `result: map` with parsed `DATA` dates
2. Run doctests - all must succeed
Polish:
1. Zdefiniuj `result: map` ze sparsowanymi datami `DATA`
2. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `map()`
* `datetime.fromisoformat()`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from pprint import pprint
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Variable `result` has invalid type, must be a list'
>>> assert all(type(element) is datetime for element in result), \
'All elements in `result` must be a datetime'
>>> pprint(result, width=30)
[datetime.datetime(1961, 4, 12, 6, 7),
datetime.datetime(1961, 4, 12, 6, 7)]
"""
from datetime import datetime
DATA = [
'1961-04-12 06:07',
'1961-04-12 06:07:00',
]
# Define `result: map` with parsed `DATA` dates
# type: map
result = ...
"""
* Assignment: Datetime ISO List
* Complexity: medium
* Lines of code: 1 lines
* Time: 2 min
English:
1. Define `result: map` with logged users from `DATA`
2. Run doctests - all must succeed
Polish:
1. Zdefiniuj `result: map` z zalogowanymi użytkownikami z `DATA`
2. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `map()`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from pprint import pprint
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Variable `result` has invalid type, must be a list'
>>> assert all(type(element) is str for element in result), \
'All elements in `result` must be a str'
>>> pprint(result, width=30)
['User logged-in: mwatney',
'User logged-in: mlewis']
"""
class User:
def __init__(self, username, password):
self.username = username
self.password = password
def login(self):
return f'User logged-in: {self.username}'
USERS = [
User('mwatney', 'Ares3'),
User('mlewis', 'Nasa69'),
]
"""
* Assignment: Datetime ISO Logs
* Complexity: medium
* Lines of code: 7 lines
* Time: 8 min
English:
1. Define `parse()` to extract date, time, level and message
2. Define `result: map` with `parse()` function applied to `DATA`
3. Run doctests - all must succeed
Polish:
1. Zdefiniuj `parse()` do wyciągnięcia dat, czasu, poziomu i wiadomości
2. Zdefiniuj `result: map` z funkcją `parse() zaaplikowaną do danych
3. Uruchom doctesty - wszystkie muszą się powieść
Hint:
* Note, that last time has no seconds
* This is not bug, time without seconds is in NASA history records [1]
References:
[1] National Aeronautics and Space Administration.
Apollo 11 timeline.
Year: 1969. Retrieved: 2021-03-25.
URL: https://history.nasa.gov/SP-4029/Apollo_11i_Timeline.htm
Hints:
* `str.splitlines()`
* `str.split(', ', maxsplit=3)`
* `date.fromisoformat()`
* `time.fromisoformat()`
* `datetime.combine()`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from pprint import pprint
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Variable `result` has invalid type, must be a list'
>>> assert all(type(row) is dict for row in result), \
'All elements in result must be dict'
>>> pprint(result)
[{'level': 'INFO',
'message': 'Terminal countdown started',
'when': datetime.datetime(1969, 7, 14, 21, 0)},
{'level': 'WARNING',
'message': 'S-IC engine ignition (#5)',
'when': datetime.datetime(1969, 7, 16, 13, 31, 53)},
{'level': 'DEBUG',
'message': 'Maximum dynamic pressure (735.17 lb/ft^2)',
'when': datetime.datetime(1969, 7, 16, 13, 33, 23)},
{'level': 'WARNING',
'message': 'S-II ignition',
'when': datetime.datetime(1969, 7, 16, 13, 34, 44)},
{'level': 'DEBUG',
'message': 'Launch escape tower jettisoned',
'when': datetime.datetime(1969, 7, 16, 13, 35, 17)},
{'level': 'DEBUG',
'message': 'S-II center engine cutoff',
'when': datetime.datetime(1969, 7, 16, 13, 39, 40)},
{'level': 'INFO',
'message': 'Translunar injection',
'when': datetime.datetime(1969, 7, 16, 16, 22, 13)},
{'level': 'INFO',
'message': 'CSM docked with LM/S-IVB',
'when': datetime.datetime(1969, 7, 16, 16, 56, 3)},
{'level': 'INFO',
'message': 'Lunar orbit insertion ignition',
'when': datetime.datetime(1969, 7, 16, 17, 21, 50)},
{'level': 'INFO',
'message': 'Lunar orbit circularization ignition',
'when': datetime.datetime(1969, 7, 16, 21, 43, 36)},
{'level': 'INFO',
'message': 'CSM/LM undocked',
'when': datetime.datetime(1969, 7, 20, 17, 44)},
{'level': 'WARNING',
'message': 'LM powered descent engine ignition',
'when': datetime.datetime(1969, 7, 20, 20, 5, 5)},
{'level': 'ERROR',
'message': 'LM 1202 alarm',
'when': datetime.datetime(1969, 7, 20, 20, 10, 22)},
{'level': 'ERROR',
'message': 'LM 1201 alarm',
'when': datetime.datetime(1969, 7, 20, 20, 14, 18)},
{'level': 'WARNING',
'message': 'LM lunar landing',
'when': datetime.datetime(1969, 7, 20, 20, 17, 39)},
{'level': 'DEBUG',
'message': 'EVA started (hatch open)',
'when': datetime.datetime(1969, 7, 21, 2, 39, 33)},
{'level': 'WARNING',
'message': '1st step taken lunar surface (CDR)',
'when': datetime.datetime(1969, 7, 21, 2, 56, 15)},
{'level': 'WARNING',
'message': 'Neil Armstrong first words on the Moon',
'when': datetime.datetime(1969, 7, 21, 2, 56, 15)},
{'level': 'DEBUG',
'message': 'Contingency sample collection started (CDR)',
'when': datetime.datetime(1969, 7, 21, 3, 5, 58)},
{'level': 'INFO',
'message': 'LMP on lunar surface',
'when': datetime.datetime(1969, 7, 21, 3, 15, 16)},
{'level': 'DEBUG',
'message': 'EVA ended (hatch closed)',
'when': datetime.datetime(1969, 7, 21, 5, 11, 13)},
{'level': 'WARNING',
'message': 'LM lunar liftoff ignition (LM APS)',
'when': datetime.datetime(1969, 7, 21, 17, 54)},
{'level': 'INFO',
'message': 'CSM/LM docked',
'when': datetime.datetime(1969, 7, 21, 21, 35)},
{'level': 'WARNING',
'message': 'Transearth injection ignition (SPS)',
'when': datetime.datetime(1969, 7, 22, 4, 55, 42)},
{'level': 'INFO',
'message': 'CM/SM separation',
'when': datetime.datetime(1969, 7, 24, 16, 21, 12)},
{'level': 'WARNING',
'message': 'Entry',
'when': datetime.datetime(1969, 7, 24, 16, 35, 5)},
{'level': 'WARNING',
'message': 'Splashdown (went to apex-down)',
'when': datetime.datetime(1969, 7, 24, 16, 50, 35)},
{'level': 'INFO',
'message': 'Crew egress',
'when': datetime.datetime(1969, 7, 24, 17, 29)}]
"""
from datetime import date, datetime, time
from typing import Literal, TypedDict
DATA = """1969-07-14, 21:00:00, INFO, Terminal countdown started
1969-07-16, 13:31:53, WARNING, S-IC engine ignition (#5)
1969-07-16, 13:33:23, DEBUG, Maximum dynamic pressure (735.17 lb/ft^2)
1969-07-16, 13:34:44, WARNING, S-II ignition
1969-07-16, 13:35:17, DEBUG, Launch escape tower jettisoned
1969-07-16, 13:39:40, DEBUG, S-II center engine cutoff
1969-07-16, 16:22:13, INFO, Translunar injection
1969-07-16, 16:56:03, INFO, CSM docked with LM/S-IVB
1969-07-16, 17:21:50, INFO, Lunar orbit insertion ignition
1969-07-16, 21:43:36, INFO, Lunar orbit circularization ignition
1969-07-20, 17:44:00, INFO, CSM/LM undocked
1969-07-20, 20:05:05, WARNING, LM powered descent engine ignition
1969-07-20, 20:10:22, ERROR, LM 1202 alarm
1969-07-20, 20:14:18, ERROR, LM 1201 alarm
1969-07-20, 20:17:39, WARNING, LM lunar landing
1969-07-21, 02:39:33, DEBUG, EVA started (hatch open)
1969-07-21, 02:56:15, WARNING, 1st step taken lunar surface (CDR)
1969-07-21, 02:56:15, WARNING, Neil Armstrong first words on the Moon
1969-07-21, 03:05:58, DEBUG, Contingency sample collection started (CDR)
1969-07-21, 03:15:16, INFO, LMP on lunar surface
1969-07-21, 05:11:13, DEBUG, EVA ended (hatch closed)
1969-07-21, 17:54:00, WARNING, LM lunar liftoff ignition (LM APS)
1969-07-21, 21:35:00, INFO, CSM/LM docked
1969-07-22, 04:55:42, WARNING, Transearth injection ignition (SPS)
1969-07-24, 16:21:12, INFO, CM/SM separation
1969-07-24, 16:35:05, WARNING, Entry
1969-07-24, 16:50:35, WARNING, Splashdown (went to apex-down)
1969-07-24, 17:29, INFO, Crew egress"""
class Log(TypedDict):
when: datetime
level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
message: str
# Define `parse()` to extract date, time, level and message
# type: Callable[[str], [Log]]
def parse(line: str) -> Log:
...
# Define `result: map` with `parse()` function applied to `DATA`
# type: map
result = ...
"""
* Assignment: CSV Format ReadTypeCast
* Complexity: easy
* Lines of code: 5 lines
* Time: 5 min
English:
1. Define function `parse(str) -> list[tuple]`
2. Define `result: map` with function `parse()` applied to `DATA`
3. Convert numeric values to `float`
4. Run doctests - all must succeed
Polish:
1. Zdefiniuj funkcję `parse(str) -> list[tuple]`
2. Zdefiniuj `result: map` z funkcją `parse()` zaaplikowaną do `DATA`
3. Przekonwertuj wartości numeryczne do `float`
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `str.strip()`
* `str.split()`
* `str.splitlines()`
* `map()`
* `float()`
* ('hello',) - one element tuple
* `(1, 2, 3) + ('hello',)` - adding tuples
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result) # expand map object
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is tuple for x in result), \
'All rows in `result` should be tuple'
>>> result # doctest: +NORMALIZE_WHITESPACE
[(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')]
"""
DATA = """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"""
# values from file (note the list[tuple] format!)
def parse() -> list[tuple]:
...
# Define `result: map` with function `parse()` applied to `DATA`
# type: map
result = ...
"""
* Assignment: CSV Format ReadTypeCast
* Complexity: easy
* Lines of code: 9 lines
* Time: 8 min
English:
1. Define `class_labels: list[str]` from header (species names)
2. Define `label_encoder: dict[int,str]` converting `class_labels`
3. Define function `parse(str) -> list[tuple]`
4. Define `result: map` with function `parse()` applied to `DATA`
5. Convert numeric values to `float`
6. Run doctests - all must succeed
Polish:
1. Zdefiniuj `class_labels: list[str]` z nagłówka (nazwy gatunków)
2. Zdefiniuj `label_encoder: dict[int,str]` przekształcając `class_labels`
3. Zdefiniuj funckję `parse(str) -> list[tuple]`
4. Zdefiniuj `result: map` z funkcją `parse()` zaaplikowaną do `DATA`
5. Przekonwertuj wartości numeryczne do `float`
6. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `str.splitlines()`
* `str.strip()`
* `str.split()`
* `result, *others = 1, 2, 3, 4`
* `dict()`
* `enumerate()`
* `map()`
* `float()`
* `('hello',)` - one element tuple
* `(1, 2, 3) + ('hello',)` - adding tuples
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result) # expand map object
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is tuple for x in result), \
'All rows in `result` should be tuple'
>>> result # doctest: +NORMALIZE_WHITESPACE
[(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')]
"""
DATA = """3,4,setosa,virginica,versicolor
5.8,2.7,5.1,1.9,1
5.1,3.5,1.4,0.2,0
5.7,2.8,4.1,1.3,2"""
"""
* Assignment: Idiom Filter Apply
* Required: yes
* Complexity: easy
* Lines of code: 7 lines
* Time: 8 min
English:
1. Filter-out lines from `DATA` when:
a. line is empty
b. line has only spaces
c. starts with # (comment)
2. Use `filter()` to apply function `valid()` to DATA
3. Define `result: filter` with result
4. Run doctests - all must succeed
Polish:
1. Odfiltruj linie z `DATA` gdy:
a. linia jest pusta
b. linia ma tylko spacje
c. zaczyna się od # (komentarz)
2. Użyj `filter()` aby zaaplikować funkcję `valid()` do DATA
3. Zdefiniuj `result: filter` z wynikiem
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* filter()
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> assert isfunction(parse), \
'Object `parse` must be a function'
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is map, \
'Variable `result` has invalid type, should be map'
>>> result = list(result)
>>> assert type(result) is list, \
'Evaluated `result` has invalid type, should be list'
>>> assert all(type(x) is dict for x in result), \
'All rows in `result` should be dict'
>>> list(result) # doctest: +NORMALIZE_WHITESPACE
[{'ip': '127.0.0.1', 'hosts': ['localhost']},
{'ip': '127.0.0.1', 'hosts': ['astromatt']},
{'ip': '10.13.37.1', 'hosts': ['nasa.gov', 'esa.int']},
{'ip': '255.255.255.255', 'hosts': ['broadcasthost']},
{'ip': '::1', 'hosts': ['localhost']}]
"""
DATA = """127.0.0.1 localhost
127.0.0.1 astromatt
10.13.37.1 nasa.gov esa.int
255.255.255.255 broadcasthost
::1 localhost"""