Advertisement
Try95th

flatten_nested_objects

Jan 21st, 2023 (edited)
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.36 KB | None | 0 0
  1. ################# recursively flatten nested dictionaries (or any iterable) ##################
  2. ## simplified version for just dictionaries @ https://stackoverflow.com/a/75196824/6146136 ###
  3. ## to just get individual nested values, see getNestedVal @ https://pastebin.com/NRxKRJPn ####
  4.  
  5. # only instances covered  by fTypes will be flattened (if they are iterable)
  6. # for non-dictionary iterables [lists/tuples/sets/etc], indices will be treated as keys
  7. # if ignore_indices is True indices of lists/tuples/sets/etc will be omitted
  8. # if ignore_singles is True keys/indices paired with the only iterable in a level will be omitted
  9. # kList MUST be a list and should contain strings only
  10. def recFlatten(obj_x, kList=[], fTypes=(dict, list), ignore_singles=False, ignore_indices=False):
  11.     idx, is_ft = False, True if fTypes=='all' else isinstance(obj_x, fTypes)
  12.     if not (is_ft and hasattr(obj_x,'__iter__')): return [(kList,obj_x)]
  13.  
  14.     try: keys, vals = list(iter(obj_x.keys())), list(iter(obj_x.values()))
  15.     except: keys, vals, idx = list(range(len(obj_x))), list(iter(obj_x)), True
  16.  
  17.     vtc, tList = [type(v) for v in vals], []
  18.     keys = [[str(ki) for ki in kList + ([] if (
  19.         (ignore_singles and vtc.count(vt)==1 and isinstance(v, fTypes))
  20.         or (ignore_indices and idx)
  21.     ) else [k])] for vt, v, k in zip(vtc, vals, keys)]
  22.  
  23.     for k, v in zip(keys, vals):
  24.         try: tList += recFlatten(v, k, fTypes, ignore_singles, ignore_indices)
  25.         except Exception as e:
  26.             print(f'Failed at {k} \ndue to {type(e)}: {e}')
  27.             return list(zip(keys, vals))
  28.     return tList
  29.  
  30. # if kSep is True --> returns the list of tuples with key-lists and values
  31. # if kSep is False --> returns a flat list of values only
  32. # if kSep is a string --> returns a dictionary with nested keys joined by kSep UNLESS:
  33. # if kSep is None or 'only_last' --> parent keys are not included for nested keys
  34. def flattenObj(origObj, kSep='_', rename={}, **rfArgs):
  35.     rk = lambda ki: rename.get(ki, ki)
  36.     klvList = recFlatten(origObj, **rfArgs)
  37.    
  38.     if kSep is None or kSep=='only_last':
  39.         rnFunc = lambda kList: rk(kList[-1] if kList else None)
  40.     elif not isinstance(kSep, str):
  41.         return klvList if kSep else [v for k, v in klvList]
  42.     else: rnFunc = lambda kList: kSep.join([rk(k) for k in kList])
  43.  
  44.     return {rnFunc(kl): v for kl,v in klvList}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement