Partition list with predicate

Steve Holden steve at holdenweb.com
Wed Apr 23 22:49:44 EDT 2008


Jared Grubb wrote:
> That almost works, except that a predicate can have "memory". For 
> example, the predicate could be "extract every other object", which 
> doesn't care about the value of the object (so you cant remove them 
> later based on value!). Or your predicate might be "remove the first 5 
> objects that are even", which means that the predicate must be run 
> against the list in forward order with only one test per element (like 
> an input/output iterator in C++; running the predicate changes the 
> predicate itself, so you cant run one pass with "pred" and then another 
> pass with "not pred" to get the rest). Example of a case where your 
> proposed solution wouldn't quite work:
> 
> class EveryOtherOne:
>    def __init__(self):
>       self.parity = False
>    def __call__(self, obj):
>       ret, self.parity = self.parity, not self.parity
>       return ret
> 
>  >>> pred = EveryOtherOne()
>  >>> lst = [1,2,2,1]
>  >>> extracted = [ obj for obj in lst if pred(obj) ]
>  >>> extracted
> [2, 1]
>  >>> lst = [ obj for obj in lst if obj not in extracted ]
>  >>> lst
> []
> 
> On Wed, Apr 23, 2008 at 6:14 PM, Brian <breily at gmail.com 
> <mailto:breily at gmail.com>> wrote:
> 
>     On Wed, Apr 23, 2008 at 9:08 PM, Jared Grubb <jared.grubb at gmail.com
>     <mailto:jared.grubb at gmail.com>> wrote:
> 
>         I guess I forgot one requirement: the removed elements need to
>         be remembered. 
> 
>         Basically, I have a list of objects in a buffer, one class
>         operates on some of the objects, but other classes use others.
>         So, a class must extract the ones it can handle, and leave the
>         rest in the buffer for the other classes to handle. 
> 
>         I haven't found a function that will both remove objects from a
>         list, but save the ones that do get removed.
> 
>         Jared
> 
>         On 23 Apr 2008, at 10:15, Tim Golden wrote:
>>         Jared Grubb wrote:
>>>         I want a function that removes values from a list if a
>>>         predicate evaluates to True. The best I could come up with is:
>>
>>         Have a look at the itertools module, and the ifilter function
>>         in particular.
>>
>>         TJG
>>         --
>>         http://mail.python.org/mailman/listinfo/python-list
> 
> 
>         --
>         http://mail.python.org/mailman/listinfo/python-list
> 
> 
>     I would do it like this:
> 
>     # This takes out the values
>     extracted = [ obj for obj in lst if pred(obj) ]
>     # This filters out any item that was extracted
>     lst = [ obj for obj in list if obj not in extracted ]
> 
So what you are saying is that you want to build *two* lists, one of 
them the ones for which the predicate is true and the other the rest.

Typical customer, doesn't bother to give us the whole specification 
until we've started programming!

How about (untested, conditional expression abuse warning):

def stripf(lst, pred):
    tlst = []
    flst = []
    for itm in lst:
      (tlst if pred(itm) else flst).append(itm)
    return tlst, flst

regards
  Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list