0

There is a nested dictionery like :

data_dict = {
 "picture":"xxx.jpg",
 "link_data":{
     "picture":"xxxxx.jpg", 
     ... 
     "child_attachments":{
            "picture":"xxxxx.jpg", 
              ... 
       }
  }
  ...
}

The problem is at every level of the dictionary, the key picture may exist, how can I get the picture's value in a most effective way?

Here's my trial, but failed:

def get_picture_url(data):
    for key, value in data.items():
        if key == "picture":
            return data[key]
        else:
            if isinstance(value, dict):
                return get_picture_url(value)

get_picture_url(data_dict)
Amir Shabani
  • 3,857
  • 6
  • 30
  • 67
jia Jimmy
  • 1,693
  • 2
  • 18
  • 38

2 Answers2

0

You are not checking the returned value of the recursive call to get_picture_url.

This should give you the top most picture in your dict:

def get_picture_url(data, picture_key="picture"):
    if not isinstance(data, dict):
        return None
    picture_url = data.get(picture_key)
    if picture_url is not None:
        return picture_url
    for value in data.values():
        picture_url = get_picture_url(value)
        if picture_url is not None:
            return picture_url
    return None
Adrien Ball
  • 440
  • 1
  • 4
  • 14
0

This should work for the general case of an arbitrarily nested dictionary with JSON-like structure:

def get_picture(data):
    # you can remove this case if the
    # input doesn't contain lists
    if isinstance(data, list):
        ans = []
        for e in data:
            ans += get_picture(e)
        return ans
    elif not isinstance(data, dict):
        return []
    else:
        ans = []
        for k, v in data.items():
            if k == 'picture':
                ans.append(v)
            else:
                ans += get_picture(v)
        return ans

It'll traverse all levels of the data structure, looking for keys named 'picture' and accumulating all of their values in a single output list. If you're sure that there are no lists in the input, we can simplify the solution a bit:

def get_picture(data):
    ans = []
    if isinstance(data, dict):
        for k, v in data.items():
            if k == 'picture':
                ans.append(v)
            else:
                ans += get_picture(v)
    return ans

Either way, it works as expected for your sample input:

data_dict = {
 "picture":"xxx.jpg",
 "link_data":{
    "picture":"xxxx.jpg",
    "child_attachments":{
        "picture":"xxxxx.jpg"
    }
  }
}

get_picture(data_dict)
=> ['xxx.jpg', 'xxxx.jpg', 'xxxxx.jpg']
Óscar López
  • 232,561
  • 37
  • 312
  • 386