рекурсивно фильтрующий кортеж внутри кортежа - PullRequest
0 голосов
/ 10 января 2019

я пытаюсь выяснить, как фильтровать кортеж внутри кортежа вот так:

input>>>filter_tree((1,2,3,4,(1,2,3)),lambda x:x%2==0)

output>>> ((2,4,(2))

вот как далеко я добрался:

 def filter_tree(tree,f):
     if type(tree)!=tuple:
           return tree
     return tuple(filter(f,tuple(filter_tree(node,f) for node in tree)))  

это работает, когда внутри кортежа нет кортежа, и я понятия не имею, что мне нужно изменить, чтобы заставить его работать (я должен использовать только рекурсии). у кого-нибудь есть идея?

Ответы [ 4 ]

0 голосов
/ 10 января 2019

Альтернативное однострочное решение, которое сохраняет рекурсивную структуру ввода:

def filter_tree(tree, filter_func):
    return tuple(filter_tree(element, filter_func) if isinstance(element, tuple) else element for element in tree if isinstance(element, tuple) or filter_func(element))

TEST

>>> print(filter_tree((0, 1, 2, (3, 4, (5, 6), 7), 8, 9, 10), lambda x: x % 2 == 0))
(0, 2, (4, (6,)), 8, 10)
>>> 

Примерно эквивалентно:

def filter_tree(tree, filter_func):

    filtered_tree = tuple()

    for element in tree:

        if isinstance(element, tuple):
            filtered_tree += (filter_tree(element, filter_func),)
        elif filter_func(element):
            filtered_tree += (element,)

    return filtered_tree
0 голосов
/ 10 января 2019

Я думаю, это то, что вы хотите.

a = (1,2,3,(1,2,3,(1,2,3,4)))

def func(x):
    return x%2==0

def foo(v):
    ans = ()
    for x in v:
        if type(x)==tuple:
            ans += (foo(x),)
        elif func(x):
            ans += (x,)
    return ans

print(foo(a))
0 голосов
/ 10 января 2019

Вот решение генератора, которое также работает:

def filter_nested_tuples(iterable, f):
    """filter elements from nested tuples from function f"""
    for x in iterable:
        if isinstance(x, tuple):
            yield tuple(filter_nested_tuples(x, f))
        elif f(x):
            yield x

def is_even(x):
    """Indicates if number is even"""
    return x % 2 == 0

tup = (1,2,3,4,(1,2,3))
print(tuple(filter_nested_tuples(tup, f=is_even)))
# (2, 4, (2,))

Примечание: Преимущество использования isinstance() над type() заключается в том, что вы хотите поддерживать несколько типов, таких как list, set, тогда вы можете просто передать кортеж типов: isinstance(x, (list, set, tuple)).

0 голосов
/ 10 января 2019

Применять функцию фильтра только непосредственно к элементам без кортежей и выполнять рекурсию только для элементов кортежей:

def filter_tree(tree, f):
    # conditional iteration over all child nodes / leaves
    return tuple(elem for elem in tree if type(elem) != tuple and f(elem)) \ 
         + tuple(filter_tree(node, f) for node in tree if type(node) == tuple)

>>> filter_tree((1,2,3,4,(1,2,3)),lambda x:x%2==0)
(2, 4, (2,))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...