Я хотел бы отобразить и отфильтровать элементы вложенных итераций в Python, соответствующие определенным условиям, например:
items = [func(item) if map_condition(item) else item for item in items if filter_condition(item)]
, но обобщенные для вложенных итераций, например, для ввода, например:
items = [[1, 2], [[3, 4, 4.0, 5], 5], 6.0, 'ciao', 7, 8, {1, 2, 3}]
применение функции nested_map_filter(items, func, map_condition, filter_condition)
примерно так:
new_items = nested_filter_map(items, str, lambda x: isinstance(x, int), lambda x: not isinstance(x, str))
new_items = nested_filter_map(items, str, None, None)
new_items = nested_filter_map(items, str, None, lambda x: not isinstance(x, float))
new_items = nested_filter_map(items, str, lambda x: isinstance(x, int), None)
new_items = nested_filter_map(items, str, lambda x: isinstance(x, int), lambda x: not isinstance(x, float))
приведет, соответственно, к:
# [['1', '2'], [['3', '4', 4.0, '5'], '5'], 6.0, '7', '8', {'2', '1', '3'}]
# [['1', '2'], [['3', '4', '4.0', '5'], '5'], '6.0', 'ciao', '7', '8', {'2', '1', '3'}]
# [['1', '2'], [['3', '4', '5'], '5'], 'ciao', '7', '8', {'2', '1', '3'}]
# [['1', '2'], [['3', '4', 4.0, '5'], '5'], 6.0, 'ciao', '7', '8', {'2', '1', '3'}]
# [['1', '2'], [['3', '4', '5'], '5'], 'ciao', '7', '8', {'2', '1', '3'}]
Есть ли стандартная конструкция или что-то в стандартной библиотекесделать это?
РЕДАКТИРОВАТЬ : я улучшил терминологию, чтобы map
/ filter
соответствовал значению встроенных модулей, и добавил больше тестовых случаев.
РЕДАКТИРОВАТЬ
Я написал что-то вроде этого, что делает работу.
( РЕДАКТИРОВАТЬ 2 ) Мои вопросы больше: я заново изобретаюрулевое колесо?Можно / удобно ли написать это как генератор?
def deep_filter_map(
items,
func=None,
map_condition=None,
filter_condition=None,
avoid=(str, bytes),
max_depth=-1):
if func is None:
def func(x): return x
if map_condition is None:
def map_condition(_): return True
if filter_condition is None:
def filter_condition(_): return True
container = type(items)
new_items = []
for item in items:
try:
no_expand = avoid and isinstance(item, avoid)
if no_expand or max_depth == 0 or item == next(iter(item)):
raise TypeError
except TypeError:
if filter_condition(item):
new_items.append(func(item) if map_condition(item) else item)
else:
new_items.append(
deep_filter_map(
item, func, map_condition, filter_condition, avoid, max_depth - 1))
return container(new_items)