Написание функции для фильтрации данных. Функция в качестве аргумента функции
Задача звучит следующим образом.
Создать функции query, select и field_filter для манипуляций с данными. Эти функции должны предоставлять возможность выбирать необходимые столбцы и производить фильтрацию по этим столбцам. Аргументы функций заданы.
Пример:
friends = [
{'name': 'Sam', 'gender': 'male', 'sport': 'Basketball'},
{'name': 'Emily', 'gender': 'female', 'sport': 'volleyball'},
]
result = query(
friends, select('name', 'gender', 'sport'), field_filter('sport', *('Basketball', 'volleyball')),
field_filter('gender', *('male'))
print(result):
[{'gender': 'male', 'name': 'Sam', 'sport': 'Basketball'}]
Мой код:
from typing import Dict, Any, Callable, Iterable
DataType = Iterable[Dict[str, Any]]
ModifierFunc = Callable[[DataType], DataType]
def query(data: DataType, selector: ModifierFunc,
*filters: ModifierFunc) -> DataType:
pass
def select(*columns: str) -> ModifierFunc:
keys = [columns]
res = []
for dict1 in field_filter():
result = dict((k, dict1[k]) for k in keys if k in dict1)
res.append(result)
return res
def field_filter(column: str, *values: Any) -> ModifierFunc:
x = []
for i in range(0, len(DataType)):
y = DataType[i]
if y[column] == values:
x.append(y)
return x
Не имел до этой задачи опыта с использованием функций в качестве аргумента иной функции. Предположил, что каждая функция должна в результате вернуть откорректированный list, и следующая уже будет корректировать результирующий list и т.д. Но IDE подсказывает, что ожидается, что результатом функций должен быть не тип данных list, а Iterable[Dict[str, Any]]. В общем и целом, я запутался. Аргументы функций задан
Ответы (1 шт):
Можно примерно так. С аннотациями разбирайтесь сами. Обратите внимание на вызовы, у вас там кортежи теряются - если он из одного элемента, над запятую ставить. И что-то еще было, забыл
def query(data: list[dict], selector: callable(list),
*filters) -> list[dict]:
res = []
for x in data:
if all(y(x) for y in filters):
d = selector(x)
res.append(d)
return res
def select(*columns: str) -> callable:
keys = [*columns]
def selector(data):
return {k: data[k] for k in keys if k in data}
return selector
def field_filter(column: str, *values:str) -> callable:
def filters(x):
return column in x and x[column] in values
return filters
friends = [
{'name': 'Sam', 'gender': 'male', 'sport': 'Basketball'},
{'name': 'Emily', 'gender': 'female', 'sport': 'volleyball'},
]
result = query(
friends,
select('name', 'gender', 'sport'),
field_filter('sport', *('Basketball', 'volleyball')),
field_filter('gender', *('male',)))
print(result)
# [{'gender': 'male', 'name': 'Sam', 'sport': 'Basketball'}]
Или так, чтоб вызов фильтра был более читабельным
def query(data: list[dict], selector: callable(list),
filter) -> list[dict]:
res = []
for x in data:
if filter(x):
d = selector(x)
res.append(d)
return res
def select(*columns: str) -> callable:
keys = [*columns]
def selector(data):
return {k: data[k] for k in keys if k in data}
return selector
def field_filter(**kwarg) -> callable:
def filters(x):
for k, v in kwarg.items():
if not(k in x and x[k] in v):
return False
return True
return filters
friends = [
{'name': 'Sam', 'gender': 'male', 'sport': 'Basketball'},
{'name': 'Emily', 'gender': 'female', 'sport': 'volleyball'},
]
result = query(
friends,
select('name', 'sport'),
field_filter(sport=('Basketball', 'volleyball'), gender=('male',))
)
print(result)