Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering function for an arbitrary nested list

I can't find out how to write this function as a lambda because of the double conditional:

def f(e):
    if not isinstance(e,list):
        if e >10:
            return e
    else:
        return filter(None,[f(y) for y in e])
my_list=[[1], [2,[3,12, [4,11,12]]], [5,6,13,14],[15]]

>>> f(my_list)
[[[12, [11, 12]]], [13, 14], [15]]

Also, what would be the pythonic way to write such a function that filters arbitrarily nested lists?

like image 224
user2314737 Avatar asked Mar 10 '23 07:03

user2314737


2 Answers

First of all, there is nothing wrong with defining a filtering or mapping function as a regular function via def if it would be a benefit to readability - remember "Readability counts" and "Sparse is better than dense". Just because there are inline lambda function in the language, does not mean you have to squeeze your logic into it.

Since you eventually want to build a generic solution for an arbitrary list depth, you can recursively apply the filtering function via map() + filter() to remove the None values:

def filter_function(e):
    if isinstance(e, list):
        return filter(None, map(filter_function, e))
    elif e > 10:
        return e

my_list = list(filter_function(my_list))  

Note that list() would be needed on Python 3.x, since filter() does not return a list.


Demo:

>>> my_list = [[1], [2, [3, 12, [4, 11, 12]]], [5, 6, 13, 14], [15]]
>>> 
>>> def filter_function(e):
...     if isinstance(e, list):
...         return filter(None, map(filter_function, e))
...     elif e > 10:
...         return e
... 
>>> 
>>> print(list(filter_function(my_list)))
[[[12, [11, 12]]], [13, 14], [15]]
like image 84
alecxe Avatar answered Mar 21 '23 09:03

alecxe


Well, this is not a best practice, but you can create a lambda function: use parenthesis to group conditions:

f = lambda e: filter(None, [f(y) for y in e]) if isinstance(e, list) else (e if e > 10 else None)

my_list = [[1], [2, [3, 12, [4, 11, 12]]], [5, 6, 13, 14], [15]]

>>> f(my_list)
[[[12, [11, 12]]], [13, 14], [15]]

For python 3 users:

f = lambda e: list(filter(None, [f(y) for y in e])) if isinstance(e, list) else (e if e > 10 else None)
like image 42
Laurent LAPORTE Avatar answered Mar 21 '23 09:03

Laurent LAPORTE