AutomaticStatic
AutomaticStatic

Reputation: 1739

Python: filter(None, [list of bools]) behavior

EDIT: After reading the suggested link, I have no idea why this has been marked as a duplicate. Sue me.

Can anyone help me understand why filter(None, [list of bools]) removes False values?

Take the following:

low = 25 
high = 35
to_match = [15, 30, 32, 99]
def check(low, high, to_match):
    return [low <= i <= high for i in to_match]

check(low, high, to_match) returns [False, True, True, False]

filter(None, check(low, high, to_match)) returns [True, True]

So I thought, Python must think False is None! But to my surprise, False is None returns False!

A) What am I missing?

B) How can I filter only None values from [True, None, False]?

Upvotes: 46

Views: 41290

Answers (2)

agf
agf

Reputation: 176800

If you want to filter out None, use:

filter(lambda x: x is not None, [list of bools])

or

[x for x in [list of bools] if x is not None]

filter takes a function, not a value. filter(None, ...) is shorthand for filter(lambda x: x, ...) -- it will filter out values that are false-y (emphasis mine):

filter(function, iterable)

Construct a list from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If iterable is a string or a tuple, the result also has that type; otherwise it is always a list. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.

Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)] if function is not None and [item for item in iterable if item] if function is None.

Upvotes: 59

Padraic Cunningham
Padraic Cunningham

Reputation: 180441

For python3 you can use None.__ne__ to only remove None, just filtering using None will remove any falsey values like [], {} 0 etc.. :

filter(None.__ne__, check(low, high, to_match))

for python2 you would need to add a lambda checking each element is not None:

filter(lambda x: x is not None,....)

If you are using python2 the stick to a list comp:

[ele for ele in check(low, high, match) if ele is not None]

Any performance gain of using filter will be offset by the lambda calls so it will actually end up slower.

Upvotes: 15

Related Questions