useful_functions.py
1 #! /usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 4 """A non-thematic collection of useful functions.""" 5 6 7 def recursively_replace(original, replacements, include_original_keys=False): 8 """Clones an iterable and recursively replaces specific values.""" 9 10 # If this function would be called recursively, the parameters 'replacements' and 'include_original_keys' would have to be 11 # passed each time. Therefore, a helper function with a reduced parameter list is used for the recursion, which nevertheless 12 # can access the said parameters. 13 14 def _recursion_helper(obj): 15 #Determine if the object should be replaced. If it is not hashable, the search will throw a TypeError. 16 try: 17 if obj in replacements: 18 return replacements[obj] 19 except TypeError: 20 pass 21 22 # An iterable is recursively processed depending on its class. 23 if hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes, bytearray)): 24 if isinstance(obj, dict): 25 contents = {} 26 27 for key, val in obj.items(): 28 new_key = _recursion_helper(key) if include_original_keys else key 29 new_val = _recursion_helper(val) 30 31 contents[new_key] = new_val 32 33 else: 34 contents = [] 35 36 for element in obj: 37 new_element = _recursion_helper(element) 38 39 contents.append(new_element) 40 41 # Use the same class as the original. 42 return obj.__class__(contents) 43 44 # If it is not replaced and it is not an iterable, return it. 45 return obj 46 47 return _recursion_helper(original)