Try95th

getNestedVal

Dec 4th, 2022 (edited)
375
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.91 KB | None | 0 0
  1. ## for checking if a nested dictionary has a certain key
  2. ## example of usage at https://stackoverflow.com/a/74680512/6146136
  3.  
  4. ## simplified version at https://pastebin.com/G92TZnnK
  5. #### [if you don't care about keys on paths to value/s]
  6.  
  7. ## to just flatten and object, see flattenObj @ https://pastebin.com/v3Fep60B
  8.  
  9.  
  10. ############### gets list of keys to every value in the dict/iterable ###############
  11. def getObjPaths(obj):
  12.     # return [] or a list of lists    
  13.     if type(obj) == str or not hasattr(obj, '__iter__'): return []
  14.     pList = []    
  15.     if type(obj) == dict:
  16.         for k, v in obj.items():  
  17.             pList += ([[k]] + [[k]+pli for pli in getObjPaths(v)])
  18.         return pList
  19.     try:
  20.         for i, v in enumerate(obj):
  21.             vp = getObjPaths(v)
  22.             pList += [[i]+pl for pl in vp if [p for p in pl if type(pl)!=int]]
  23.         return pList
  24.     except: return []
  25. #####################################################################################
  26.  
  27.  
  28. ######### retrieved a nested value if givent the list of keys on its "path" #########
  29. def getVal_byPath(obj, kPath:list, printError=False, returnError=False):
  30.     try:
  31.         for k in kPath: obj = obj[k]
  32.         return obj
  33.     except Exception as e:
  34.         errMsg = f'could not access {kPath} - {e}'
  35.         if printError: print(errMsg)
  36.         return errMsg if returnError else None
  37. #####################################################################################
  38.  
  39.  
  40. ###### checks if a kList ends with lastKey  AND contains parentKeys [in order] ######
  41. def matchedPath(kList:list, lastKey:str, parentKeys:list=[]):
  42.     if not kList[-1:] == [lastKey]: return False
  43.     if not parentKeys: return True
  44.  
  45.     kLen = len(kList)
  46.     pPosList = [(kList+[pk]).index(pk) for pk in parentKeys]
  47.     pPosList = [(-1 if p==kLen else p) for p in pPosList]
  48.     return -1 not in pPosList and sorted(pPosList) == pPosList
  49. #####################################################################################
  50.  
  51.  
  52. ####### retrieves from nObj 1st or all value/s paired to "nKey"  at any depth #######
  53. def getNestedVal(nObj,nKey:str,rForm='just_val',pKeys=[],objName='obj'):
  54.     pathList = getObjPaths(nObj)
  55.     if isinstance(nKey,str) or not hasattr(nKey,'__iter__'): nKey=[nKey]
  56.     vpli = [p for p in pathList if any(
  57.         [matchedPath(p, k, pKeys) for k in nKey]  
  58.     )]
  59.     if rForm[-4:] != '_all': vpli = vpli[:1]
  60.     vpli = [{'val': getVal_byPath(nObj, p), 'path': p,  
  61.         'expr': (f'{objName}'+''.join(f'{[k]}' for k in p)
  62.     )} for p in vpli]
  63.     if rForm.startswith('just_val'): vpli = [v['val'] for v in vpli]
  64.     if rForm.startswith('just_path'): vpli = [v['path'] for v in vpli]
  65.     if rForm.startswith('just_expr'): vpli = [v['expr'] for v in vpli]
  66.     if rForm[-4:] == '_all': return vpli  
  67.     return vpli[0] if vpli else None
  68. #####################################################################################
Advertisement
Add Comment
Please, Sign In to add comment