Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a parameter through a python filter function

Tags:

python

I'm trying to filter a list of words/phrases by some keyword. All the examples I've found of the filter() function have been using numbers, so I'm wondering if this is even possible. I know that filter() will put an item into the resulting list if the function it calls returns True.

Let's say I have something like this:

def filtCheck(item, filt):
    if filt in item:
        return True

def funct():
    filt = 'Hi'
    set1 = ['Hello, world', 'Hi there', 'Hi friend']
    set2 = filter(filtCheck(filt), set1)

    print set2

Here is where I get confused. How exactly would I write that first parameter on the set2 line? Obviously not the way its written since my filtCheck function takes two parameters and I only provide one. Do I need to modify my filtCheck function too? But if I take the item parameter out of it, there's no string to check if filt is in.

like image 455
Xonal Avatar asked Oct 23 '13 19:10

Xonal


4 Answers

You could use a lambda (see also http://docs.python.org/2/reference/expressions.html#lambda):

set2 = filter(lambda item: filtCheck(item, 'Hi'), set1)

Or you could use functools.partial:

from functools import partial
set2 = filter(partial(filtCheck, filt="Hi"), set1)

Or you could skip the filter function and use a list comprehension:

set2 = [item for item in set1 if filtCheck(item, "Hi")]

# or simply

set2 = [item for item in set1 if "Hi" in item]
like image 128
codeape Avatar answered Sep 27 '22 21:09

codeape


Easier to switch to a list-comp:

filt = 'Hi'
set1 = ['Hello, world', 'Hi there', 'Hi friend']
set2 = [greeting for greeting in set1 if filt in greeting]
like image 32
Jon Clements Avatar answered Sep 27 '22 20:09

Jon Clements


You could use currying:

def filtCheck(filt):
    return lambda item: filt in item

def funct():
    filt = 'Hi'
    set1 = ['Hello, world', 'Hi there', 'Hi friend']
    set2 = filter(filtCheck(filt), set1)
    print set2
like image 20
A.E. Drew Avatar answered Sep 27 '22 21:09

A.E. Drew


The most direct modification to this code would be to have filtCheck return a function rather than a boolean value:

def filtCheck(value):
    def is_in_list(lst):
        return value in lst
    return is_in_list

For your purposes, the function argument for filter is any function that takes exactly one parameter and returns a boolean value indicating whether or not it should be included in the result.

However, from the filter docs (http://docs.python.org/2/library/functions.html#filter),

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.

Combining this equivalency with the fact that filter is deprecated in python3, I would suggest you use list comprehensions:

def filtCheck(item, filt):
    if filt in item:
        return True

set2 = [item for item in set1 if filtCheck(filt, item)] 

This can be further simplified to get rid of the need to use filtCheck altogether:

def funct():
    filt = 'Hi'
    set1 = ['Hello, world', 'Hi there', 'Hi friend']
    set2 = [item for item in set1 if filt in item]

    print set2
like image 45
John Spong Avatar answered Sep 27 '22 21:09

John Spong