fnc
Functional programming in Python with generators and other utilities.
Links
- Project: https://github.com/dgilland/fnc
- Documentation: https://fnc.readthedocs.io
- PyPI: https://pypi.python.org/pypi/fnc/
- Github Actions: https://github.com/dgilland/fnc/actions
Features
- Functional-style methods that work with and return generators.
- Shorthand-style iteratees (callbacks) to easily filter and map data.
- String object-path support for references nested data structures.
- 100% test coverage.
- Python 3.6+
Quickstart
Install using pip:
pip3 install fnc
Import the main module:
import fnc
Start working with data:
users = [
{'id': 1, 'name': 'Jack', 'email': '[email protected]', 'active': True},
{'id': 2, 'name': 'Max', 'email': '[email protected]', 'active': True},
{'id': 3, 'name': 'Allison', 'email': '[email protected]', 'active': False},
{'id': 4, 'name': 'David', 'email': '[email protected]', 'active': False}
]
Filter active users:
# Uses "matches" shorthand iteratee: dictionary
active_users = fnc.filter({'active': True}, users)
# <filter object at 0x7fa85940ec88>
active_uesrs = list(active_users)
# [{'name': 'Jack', 'email': '[email protected]', 'active': True},
# {'name': 'Max', 'email': '[email protected]', 'active': True}]
Get a list of email addresses:
# Uses "pathgetter" shorthand iteratee: string
emails = fnc.map('email', users)
# <map object at 0x7fa8577d52e8>
emails = list(emails)
# ['[email protected]', '[email protected]', '[email protected]', '[email protected]']
Create a dict
of users keyed by 'id'
:
# Uses "pathgetter" shorthand iteratee: string
users_by_id = fnc.keyby('id', users)
# {1: {'id': 1, 'name': 'Jack', 'email': '[email protected]', 'active': True},
# 2: {'id': 2, 'name': 'Max', 'email': '[email protected]', 'active': True},
# 3: {'id': 3, 'name': 'Allison', 'email': '[email protected]', 'active': False},
# 4: {'id': 4, 'name': 'David', 'email': '[email protected]', 'active': False}}
Select only 'id'
and 'email'
fields and return as dictionaries:
# Uses "pickgetter" shorthand iteratee: set
user_emails = list(fnc.map({'id', 'email'}, users))
# [{'email': '[email protected]', 'id': 1},
# {'email': '[email protected]', 'id': 2},
# {'email': '[email protected]', 'id': 3},
# {'email': '[email protected]', 'id': 4}]
Select only 'id'
and 'email'
fields and return as tuples:
# Uses "atgetter" shorthand iteratee: tuple
user_emails = list(fnc.map(('id', 'email'), users))
# [(1, '[email protected]'),
# (2, '[email protected]'),
# (3, '[email protected]'),
# (4, '[email protected]')]
Access nested data structures using object-path notation:
fnc.get('a.b.c[1][0].d', {'a': {'b': {'c': [None, [{'d': 100}]]}}})
# 100
# Same result but using a path list instead of a string.
fnc.get(['a', 'b', 'c', 1, 0, 'd'], {'a': {'b': {'c': [None, [{'d': 100}]]}}})
# 100
Compose multiple functions into a generator pipeline:
from functools import partial
filter_active = partial(fnc.filter, {'active': True})
get_emails = partial(fnc.map, 'email')
get_email_domains = partial(fnc.map, lambda email: email.split('@')[1])
get_active_email_domains = fnc.compose(
filter_active,
get_emails,
get_email_domains,
set,
)
email_domains = get_active_email_domains(users)
# {'example.com', 'example.org'}
Or do the same thing except using a terser "partial" shorthand:
get_active_email_domains = fnc.compose(
(fnc.filter, {'active': True}),
(fnc.map, 'email'),
(fnc.map, lambda email: email.split('@')[1]),
set,
)
email_domains = get_active_email_domains(users)
# {'example.com', 'example.org'}
For more details and examples, please see the full documentation at https://fnc.readthedocs.io.