Skip to content

Instantly share code, notes, and snippets.

@bplaxco
Last active March 4, 2016 17:34
Show Gist options
  • Save bplaxco/bed66d1ab7e73cca8097 to your computer and use it in GitHub Desktop.
Save bplaxco/bed66d1ab7e73cca8097 to your computer and use it in GitHub Desktop.
Quickly runs `func` on elements in dict or list/set/tuple climbing down the nested elements.
import copy
def next(a, i):
j = a.index(i) + 1
return a[j] if j < len(a) else None
# end next
def get_keys(x, default=()):
if hasattr(x, 'keys'):
return x.keys()
elif hasattr(x, '__iter__'):
return range(0, len(x))
else:
return default
# end get_keys
def has_key(x, key):
if key == None:
return False
if hasattr(x, 'keys'):
return key in x
elif hasattr(x, '__iter__'):
return key < len(x)
# end get_keys
def is_pushable(x):
return hasattr(x, 'keys') or hasattr(x, '__iter__')
# end is_pushable
def normalize(obj, func=unicode, functional=True):
# Set functional to False to get more speed
obj = copy.deepcopy(obj) if functional else obj
stack = []
stack_len = stack.__len__
push = stack.append
pop = stack.pop
keys = get_keys(obj)
i = keys and keys[0]
start = bool(keys)
while start:
if has_key(obj, i):
el = obj[i]
if is_pushable(el):
push((obj, keys, next(keys, i)))
obj, keys = el, get_keys(el)
i = keys[0]
else:
obj[i] = func(el)
i = next(keys, i)
else:
if stack_len():
obj, keys, i = pop()
else:
break
return obj
# normalize
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment