简体   繁体   中英

Get list of all sub-keys from a python dictionary

I have some dictionaries(json output). I want to get the base element which can be a list of strings or a string. Currently I am doing it like this:-

folder="shared/"
files=os.listdir('shared')


for f in files:
    f=folder+f
    print(f)
    with open(f) as f:
        data = json.load(f)
    #data is a dict now with sub-keys
    for key,value in data.items():
        if value.keys():
            print(value)
    break

This is the input dictionary that was read by the python code:-

{
  "shortshirt": {
    "ralphlauren": {
      "classic": [
        "That Ralph Lauren classic fit is a timeless look!",
        "Nice choice. Can’t go wrong with Ralph Lauren"
      ]
    }
  },
  "socks": {
    "": {
      "": ["Have to find the right socks to keep your feet cozy"]
    }
  }
}

And this is the output that I am getting:-

{'ralphlauren': {'classic': ['That Ralph Lauren classic fit is a timeless look!', 'Nice choice. Can’t go wrong with Ralph Lauren']}}
{'': {'': ['Have to find the right socks to keep your feet cozy']}}

But this is what I want:-

keys=[["shortshirt","ralphlauren","classic"],["socks"]]

value=[['That Ralph Lauren classic fit is a timeless look!', 'Nice choice. Can’t go wrong with Ralph Lauren'], ['Have to find the right socks to keep your feet cozy']]

But I don't know whether to have 2 or 3 level nested loops. If I have an inner loop and in actual there was no nested key then I get the value error. I want to get all the nested keys in a separate list and the base value or values like on the lowest level in another list, any help regarding this will be highly appreciated.

Generators are useful for this problem. Strategies –

  • Keys: keep track of the current recursion path. Yield the current path as soon as you hit a leaf.

  • Values: only yield leaves.

Code:

def getitems(obj):

  def getkeys(obj, stack):
    for k, v in obj.items():
      k2 = ([k] if k else []) + stack # don't return empty keys
      if v and isinstance(v, dict):
        for c in getkeys(v, k2):
          yield c
      else: # leaf
        yield k2

  def getvalues(obj):
    for v in obj.values():
      if not v: continue
      if isinstance(v, dict):
        for c in getvalues(v):
          yield c
      else: # leaf
        yield v if isinstance(v, list) else [v]

  return list(getkeys(obj,[])), list(getvalues(obj))

Input:

{
  "shortshirt": {
    "ralphlauren": {
      "classic": [
        "That Ralph Lauren classic fit is a timeless look!",
        "Nice choice. Can't go wrong with Ralph Lauren"
      ]
    }
  },
  "socks": {
    "": {
      "": ["Have to find the right socks to keep your feet cozy"]
    }
  }
}

Output:

# keys
[['classic', 'ralphlauren', 'shortshirt'], ['socks']]

# values
[['That Ralph Lauren classic fit is a timeless look!', "Nice choice. Can't go wrong with Ralph Lauren"], ['Have to find the right socks to keep your feet cozy']]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM