views:

121

answers:

7

I probably didn't ask correctly: I would like a list value that can match any list: the "inverse" of (None,) but even with (None,) it will match item as None (which I don't want)

The point is I have a function working with: [x for x in my_list if x[field] not in filter_list]

and I would like to filter everything or nothing without making tests like: if filter_list==(None,): return [] and if filter_list==('*',): return my_list

PS: I wanted to simplify my question leading to some errors (list identifier) or stupid thing [x for x in x] ;)


Hi,

I need to do some filtering with list comprehension in python.

if I do something like that:

[x for x in list if x in (None,)]

I get rid of all values, which is fine

but I would like to have the same thing to match everything

I can do something like:

[x for x in list if x not in (None,)]

but it won't be homogeneous with the rest

I tried some things but for example (True,) matches only 1

Note than the values to filter are numeric, but if you have something generic (like (None,) to match nothing), it would be great

Thanks Louis

+5  A: 

The better syntax would be:

[x for x in lst if x is None]
[x for x in lst if x is not None]
SilentGhost
plz read the rephrasing of question
Louis
+1  A: 

You don't need an if, you can just say

[x for x in list]
Skilldrick
How can you justify this:>>> l = [None, 1, 3]>>> [x for x in l][None, 1, 3]
aatifh
@aatifh: that's not python syntax
SilentGhost
the `if` was because I filter on a field: ti's now correct in question
Louis
+4  A: 

What do you mean by

I would like to have the same thing to match everything

Just do

[x for x in list]

and every item in list is matched.

plz read the rephrasing of question
Louis
+1  A: 

but I would like to have the same thing to match everything

To match everything, you don't need if statement

[x for x in list1]

or If you really like to do

[x for x in list1 if x in [x]]
S.Mark
plz read the rephrasing of question
Louis
A: 

Answering your revised question: the list that "matches" all possible values is effectively of infinite length. So you can't do what you want to do without an if test. I suggest that your arg should be either a list or one of two values representing the "all" and "none" cases:

FILTER_NONE = object() # or []
FILTER_ALL = object()

def filter_func(alist, filter_list):
    if filter_list is FILTER_ALL:
        return []
    elif filter_list is FILTER_NONE:
        return alist
        # or maybe alist[:] # copy the list
    return [x for x in alist if x not in filter_list]

If filter_list is large, you may wish the replace the last line by:

    filter_set = set(filter_list)
    return [x for x in alist if x not in filter_set]

Alternatively, don't bother; just document that filter_list (renamed as filter_collection) can be anything that supports __contains__() and remind readers that sets will be faster than lists.

John Machin
+3  A: 

You could change your program to accept a filter object, instead of a list.

The abstract base filter would have a matches method, that returns true if x *matches".

Your general case filters would be constructed with a list argument, and would filter on membership of the list - the matches function would search the list and return true if the argument was in the list.

You could also have two special subclasses of the filter object : none and all.

These would have special match functions which either always return true (all) or false (none).

Alex Brown
+5  A: 

__contains__ is the magic method that checks if something is in a sequence:

class everything(object):
    def __contains__(self, _):
        return True           

for x in (1,2,3):
    print x in everything()
THC4k