I have a dictionary object, and I want to extract a subset of the dictionary (i.e. return another dictionary), which contains all elements of the parent dictionary where the key matches a certain criteria.
For example:
parent_dict = {1: 'Homer',
2: 'Bart',
3: 'Lisa',
4: 'Marge',
5: 'Maggie'
}
def filter_func(somedict, key_criteria_func):
pass
I want to write (in a pythonic way), filter_func
, so that I can call it like this:
filter_func(parent_dict, ">2 and <4")
which will return the new dict:
{ 3: 'Lisa' }
What is the most pythonic way to write filter_func?
To keep things simple, I will limit the criteria to simple boolean operations.
[[Edit]]
This is the output when I try the following command:
>>> {key:val for key,val in parent_dict.iteritems() if 2 < key < 4 }
File "<stdin>", line 1
{key:val for key,val in parent_dict.iteritems() if 2 < key < 4 }
^
SyntaxError: invalid syntax
BTW, I'm running Python 2.6.5
Solution
Starting from python 2.7, you can use dictionary comprehension. There are like list comprehensions, but applied to a dictionary:
>>> parent_dict = {1: 'Homer',
... 2: 'Bart',
... 3: 'Lisa',
... 4: 'Marge',
... 5: 'Maggie'
... }
>>> {key:val for key,val in parent_dict.iteritems() if 2 < key < 4 }
1: {3: 'Lisa'}
You probably don't need to make it a function, but if you do, you can just use a lambda function as a filter:
>>> def filter_func(somedict, key_criteria_func):
... return {k:v for k, v in somedict.iteritems() if key_criteria_func(k)}
...
... filter_func(parent_dict, lambda x: 2 < x < 4)
2: {3: 'Lisa'}
For Python 2.6.5 and all version before 2.7, replace the dict comprehension with:
dict((k,v) for k,v in parent_dict.iteritems() if 2 < k < 4)
Why a lambda function ?
Lambda function are not magic, it's just a way to easily create fonction on the fly. You can do everything you do with lambda
witout it, the only difference is that lambdas are expression, and therefor can be used directly between parenthis.
Compare:
>>> func = lambda x: 2 < x < 4
>>> func(3)
True
With:
>>> def func(x):
... return 2 < x < 4
...
>>> func(3)
True
It's exactly the same and produce the same function, except the lambda function won't have a name. But you don't care, on your case you don't need a name, you just need a reference to call it, and the variable func
contains this reference.
The lambda syntax is weird because:
def var(param):
but var = lambda param:
. Nothing magic, it's just syntaxlambda
: the return result must fit in one instruction.return
keyword: the right part of the lambda is returned automaticallyNow the nice thing with a lamda, is that since it's an expression, you can use it between parenthese, meaning you can create and pass your fonction à the same time.
Compare:
>>> filter_func(parent_dict, lambda x: 2 < x < 4)
With:
>>> def func(x):
... return 2 < x < 4
...
>>> filter_func(parent_dict, func)
It's exactly the same. The lambda is just shorter.
The hard part here is to understand that you can pass a function as a parameter in Python because everything in Python is an object, including functions.
You can even do this:
>>> def func():
... print "test"
...
>>> ref_to_func = func # assign the function refence to another var
>>> del func # delete this label
>>> ref_to_func() # call the function from this label
test
And you can even define a fonction on one line:
>>> def func(): print "test"
>>> func()
test
But you can't do this:
filter_func(parent_dict, def func(x): 2 < x 4 )
Which is where lambdas are useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With