How to write this python snippet in functional programming style?
Question:
How can I write the line below in functional python using e.g. toolz?
dct1 = {1: 1, 2: 2}
dct2 = {2:2}
dct3 = {2:2, 3:3}
common_keys = set(dct1.keys()) & set(dct2.keys()) & set(dct3.keys())
Answers:
Actualy your question is very unclear. I will try to help you with:
First of all, you don’t need to use set
over dict.keys()
:
dct1.keys() & dct2.keys() & dct3.keys()
# returns {2}
You can use reduce
function for your puprose:
from functools import reduce
def key_intersection(*dicts):
if len(dicts) == 0:
return set([])
if len(dicts) == 1:
return set(dicts[0])
return reduce(lambda l, r: l & r.keys(), dicts[1:], set(dicts[0]))
key_intersection(dct1, dct2, dct3)
If you want to try to write this in a functional style:
from functools import reduce
dct1 = {1: 1, 2: 2}
dct2 = {2: 2}
dct3 = {2: 2, 3: 3}
shared_keys = reduce(set.intersection, map(set, map(dict.keys, [dct1, dct2, dct3])))
First we create a list of the dictionaries.
Then we map
the dict.keys
function to each of them.
Then we map them to set
giving us sets of keys for each dictionary.
Finally, we reduce
those sets with the set.intersection
function.
Here is a clean way using toolz
. Using toolz.pipe
and toolz.curried
often makes things easier to compose and easier to read:
import operator as op
from toolz import pipe
from toolz.curried import map, reduce
pipe(
[dct1, dct2, dct3],
map(op.methodcaller("keys")),
reduce(op.and_)
)
I found your question clear, and I would say this is the best functional toolz
-style way of doing this. This pattern is powerful and can be extended to more complicated problems, so it is worth learning.
How can I write the line below in functional python using e.g. toolz?
dct1 = {1: 1, 2: 2}
dct2 = {2:2}
dct3 = {2:2, 3:3}
common_keys = set(dct1.keys()) & set(dct2.keys()) & set(dct3.keys())
Actualy your question is very unclear. I will try to help you with:
First of all, you don’t need to use set
over dict.keys()
:
dct1.keys() & dct2.keys() & dct3.keys()
# returns {2}
You can use reduce
function for your puprose:
from functools import reduce
def key_intersection(*dicts):
if len(dicts) == 0:
return set([])
if len(dicts) == 1:
return set(dicts[0])
return reduce(lambda l, r: l & r.keys(), dicts[1:], set(dicts[0]))
key_intersection(dct1, dct2, dct3)
If you want to try to write this in a functional style:
from functools import reduce
dct1 = {1: 1, 2: 2}
dct2 = {2: 2}
dct3 = {2: 2, 3: 3}
shared_keys = reduce(set.intersection, map(set, map(dict.keys, [dct1, dct2, dct3])))
First we create a list of the dictionaries.
Then we map
the dict.keys
function to each of them.
Then we map them to set
giving us sets of keys for each dictionary.
Finally, we reduce
those sets with the set.intersection
function.
Here is a clean way using toolz
. Using toolz.pipe
and toolz.curried
often makes things easier to compose and easier to read:
import operator as op
from toolz import pipe
from toolz.curried import map, reduce
pipe(
[dct1, dct2, dct3],
map(op.methodcaller("keys")),
reduce(op.and_)
)
I found your question clear, and I would say this is the best functional toolz
-style way of doing this. This pattern is powerful and can be extended to more complicated problems, so it is worth learning.