2

Let's say we have the following...

pract={
  "hello": {
    "more": 1,
    "some": 2,
    "yes": [
      {
        "dicct": 1
      },
      {
        "more_dict": 4
      }
    ]
  }
}

I have an embedded dict/list. I need to get all single values. So in this instance my result would be...

[1, 2, 1, 4]

Ideally, I would like to keep the direct parent, so this would be better...

[("more",1), ("some",2), ("dicct", 1), ("more_dict", 4)]

This is my recursive attempt...

def grab_children(father, result):
    if type(father) == type([]):
        for e in father:
            if isinstance(e, dict):
                grab_children(e, result)
    else:
        for child_key, child_value in father.items():
            if isinstance(child_value, dict):
                grab_children(child_value, result)
            else:
                result.append((child_key, child_value))

Which I run as so...

child = []
grab_children(pract, child)

But when I print the child array, I get...

[('more', 1), ('some', 2), ('yes', [{'dicct': 1}, {'more_dict': 4}])]

Clearly not the output I want. What is wrong with my solution?

funnydman
  • 9,083
  • 4
  • 40
  • 55
buydadip
  • 8,890
  • 22
  • 79
  • 154

1 Answers1

2

A generator works well for this kind of thing:

Code:

def get_terminal_nodes(data):
    if isinstance(data, list):
        for item in data:
            for i in get_terminal_nodes(item):
                yield i

    elif isinstance(data, dict):
        for k, item in data.items():
            if isinstance(item, (list, dict)):
                for i in get_terminal_nodes(item):
                    yield i
            else:
                yield k, item

Test Code:

pract = {
    "hello": {
        "more": 1,
        "some": 2,
        "yes": [{"dicct": 1}, {"more_dict": 4}]}
}

flat_data = dict(get_terminal_nodes(pract))
print(flat_data)

Results:

{'more': 1, 'some': 2, 'dicct': 1, 'more_dict': 4}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • This works perfectly, however I have never heard of generators so I have no idea how this is working. – buydadip Jan 22 '18 at 06:23
  • The magic is in the `yield`. Go through the link above. You use it like any iterator. But basically it does sort on an early return and then starts up where it left off. They are very slick in cases like these. – Stephen Rauch Jan 22 '18 at 06:25
  • 1
    Yeah, that's why I deleted my comment, I found an approach that works for me. Thanks for the help though. – buydadip Jan 22 '18 at 20:32