2

I'm a beginner at python and faced problem with getting nested dictionary values. So i look up stackoverflow and in here: 1 i found this solution:

dic={"a":{"b":2}, "c":{"d":{"e":3}}}

def deep_find(dic,keys, default=None):
    return print(reduce(lambda di, key: di.get(key, default) if isinstance(di, dict) else default, keys.split("."), dic))

deep_find(dic,"c.d.e")`

And it's beyond my understanding. As i know reduce(lambda...) takes as arguments first to values, but here it seems to take as first argument the whole dict object. I'm really lost here, can, please someone explain step by step logic of this script?

Upd:

So i made up some simple dict to play with it in reduce+lamda expressions. Using print() i found that first variable of lambda depends on list of keys we provide before iterable dictionary.

from functools import reduce
d={1:2, 3:4,5:6}
k="1.3.5"
def get(d,ks):
    reduce(lambda a,b: print(a,",",b,".") and a*b, ks, d)

get(d,k)

In this example first "a" value would be whole dict "d" and first "b" value would be a first key value in "k" which is "1" and it doesn't matter is there set of keys or only one key provided: first "a" value will be whole dictionary . In case we don't provide keys before dictionary- function will iterate only on key values. And that's all because if we put keys list before dictiinary, then keys will be the iterable and dict will be the initializer so he will become first argument.

  • 1
    Try seeing what `reduce` does and rewrite it using a `for` loop. Apply the function and save the result. You could find a python version of `reduce` and substitute your values in. – GeeTransit Jun 23 '19 at 03:28
  • You should take the accepted answer in the question you linked. `reduce` is not that elegant and readable. – Austin Jun 23 '19 at 03:29

1 Answers1

0

Well. First you should see how reduce() works If we have a function fn and a list l=[a,b,c,d] reduce(fn, l) = fn(fn(fn(a,b),c),d) fn = lambda ....

Lambda expression of example converts the string to a list to be easier for manipulation ("c.d.e".split('.') = [c,d,e]) The lambda says if the key is in the row we want then take the value of nested loop else if it is a child node so take the key of dictionary.

  • Damn! Thank you so much!!! Do i understand correctly that lambda checks element, and if it is a nested dictionary with "if isinstance" and if it is it applies .get() with key to it? – user11686813 Jun 23 '19 at 04:48