4.5. Filter¶

4.5.1. Rationale¶

• Select elements from sequence

• Generator (lazy evaluated)

• Built-in

Syntax:

• filter(callable, *iterables)

• required callable - Function

• required iterables - 1 or many sequence or iterator objects

>>> def even(x):
...     return x % 2 == 0
>>>
>>> result = (x for x in range(0,5) if even(x))
>>> result = filter(even, range(0,5))

>>> result = (x for x in range(0,5) if x%2==0)
>>> result = filter(lambda x: x%2==0, range(0,5))


4.5.2. Problem¶

Plain code:

>>> def even(x):
...     return x % 2 == 0
>>>
>>>
>>> DATA = [1, 2, 3, 4, 5, 6]
>>> result = []
>>>
>>> for x in DATA:
...     if even(x):
...         result.append(x)
>>>
>>> print(result)
[2, 4, 6]


Comprehension:

>>> def even(x):
...     return x % 2 == 0
>>>
>>>
>>> DATA = [1, 2, 3, 4, 5, 6]
>>> result = [x for x in DATA if even(x)]
>>>
>>> print(result)
[2, 4, 6]


4.5.3. Solution¶

>>> def even(x):
...     return x % 2 == 0
>>>
>>>
>>> DATA = [1, 2, 3, 4, 5, 6]
>>> result = filter(even, DATA)
>>>
>>> list(result)
[2, 4, 6]


4.5.4. Lazy Evaluation¶

>>> def even(x):
...     return x % 2 == 0
>>>
>>>
>>> DATA = [1, 2, 3, 4, 5, 6]
>>> result = filter(even, DATA)
>>>
>>> next(result)
2
>>> next(result)
4
>>> next(result)
6
>>> next(result)
Traceback (most recent call last):
StopIteration


4.5.5. Use Cases¶

>>> people = [
...     {'age': 21, 'name': 'Jan Twardowski'},
...     {'age': 25, 'name': 'Mark Watney'},
...     {'age': 18, 'name': 'Melissa Lewis'}]
>>>
>>>
...     return person['age'] >= 21
>>>
>>>
>>> list(result)
[{'age': 21, 'name': 'Jan Twardowski'},
{'age': 25, 'name': 'Mark Watney'}]

>>> people = [
...     {'is_astronaut': False, 'name': 'Jan Twardowski'},
...     {'is_astronaut': True, 'name': 'Mark Watney'},
...     {'is_astronaut': True, 'name': 'Melissa Lewis'}]
>>>
>>>
>>> def astronaut(person):
...     return person['is_astronaut']
>>>
>>>
>>> result = filter(astronaut, people)
>>> list(result)
[{'is_astronaut': True, 'name': 'Mark Watney'},
{'is_astronaut': True, 'name': 'Melissa Lewis'}]

>>> astronauts = ['Mark Watney', 'Melissa Lewis']
>>>
>>> people = ['Jan Twardowski', 'Mark Watney',
...           'Melissa Lewis', 'Jimenez']
>>>
>>>
>>> def is_astronaut(person):
...     return person in astronauts
>>>
>>>
>>> result = filter(is_astronaut, people)
>>> list(result)
['Mark Watney', 'Melissa Lewis']


4.5.6. Performance¶

>>> # %%timeit -r 10 -n 100_000
>>> # result = (x for x in range(0,5) if x%2==0)
>>> # 490 ns ± 44 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)

>>> # %%timeit -r 10 -n 100_000
>>> # result = filter(lambda x: x%2==0, range(0,5))
>>> # 384 ns ± 34.2 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)


4.5.7. Assignments¶

"""
* Assignment: Idioms Filter Chain
* Complexity: easy
* Lines of code: 5 lines
* Time: 8 min

English:
1. Use generator expression to create numbers
2. In generator use range() to get numbers from 1 to 33
(inclusive) divisible by 3
3. Use filter() to get odd numbers from numbers
4. Use map() to cube all numbers in numbers
5. Create result: float with arithmetic mean of numbers
6. Do not use lambda expressions
7. Run doctests - all must succeed

Polish:
1. Użyj wyrażenia generatorowego do stworzenia numbers
2. W generatorze użyj range() aby otrzymać liczby od 1 do 33
(włącznie) podzielne przez 3
3. Użyj filter() aby otrzymać liczby nieparzyste z numbers
4. Użyj map() aby podnieść wszystkie liczby w numbers do sześcianu
5. Stwórz result: float ze średnią arytmetyczną z numbers
6. Nie używaj wyrażeń lambda
7. Uruchom doctesty - wszystkie muszą się powieść

Hints:
* type cast to list() to expand generator before calculating mean
* mean = sum(...) / len(...)
* TypeError: object of type 'map' has no len()
* ZeroDivisionError: division by zero

Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction

>>> isfunction(odd)
True
>>> isfunction(cube)
True
>>> type(result) is float
True
>>> result
11502.0
"""

def odd(x):
return x % 2

def cube(x):
return x ** 3

# float: generator expr with numbers from 1 to 33 (inclusive) divisible by 3
#        filter out even numbers; cube result; calculate mean
result: float