Suor/funcy

New function: leaf

Closed this issue · 3 comments

I'm not sure about the name but the idea is to return the leaf node for given key in mapping of (possible deeply nested) mappings.

from collections import Mapping

def leaf(obj, key):
    item = obj.get(key, None)

    if item is None or isinstance(item, Mapping):
        for subkey in iter(obj):
            item = obj.get(subkey, None)
            if isinstance(item, Mapping):
                try:
                    return leaf(item, key)
                except KeyError:
                    pass
    else:
        return item
    raise KeyError(key)

Usage:

d = {
    1: 'first',
    2: {
        3: 'second',
        4: 'third'
    }
}

leaf(1)  # 'first'
leaf(2)  # KeyError
leaf(3)  # 'second'
Suor commented

This is very strange and very custom function:

  • why can't I store trees with lists, tuples or objects?
  • what if I need both 1st and 2nd leaves?
  • also there could be different tree walking methods.

Probably the right approach would be using higher order parametric function like Clojures tree-seq (mind branch? and children parameters) returning an iterator of leaves. So that you can write:

nth(n, ileaves(d, follow=isa(dict), children=lambda x: x.values()))

Hmm I agree with you. I have to check the Clojure link you provided thoroughly.

Suor commented

Thinking a bit more about it I think you probably need more efficient data structure. Now you have to iterate through all the dict unless it contains a key you seek. Maybe you should just flatten this to regular dict and then work with it.