def flatten(nested_dict, separator="<STR_LIT:_>", root_keys_to_ignore=set()):
assert isinstance(nested_dict, dict), "<STR_LIT>"<EOL>assert isinstance(separator, six.string_types), "<STR_LIT>"<EOL>flattened_dict = dict()<EOL>def _flatten(object_, key):<EOL><INDENT>"""<STR_LIT>"""<EOL>if not object_:<EOL><INDENT>flattened_dict[key] = object_<EOL><DEDENT>elif isinstance(object_, dict):<EOL><INDENT>for object_key in object_:<EOL><INDENT>if not (not key and object_key in root_keys_to_ignore):<EOL><INDENT>_flatten(object_[object_key], _construct_key(key,<EOL>separator,<EOL>object_key))<EOL><DEDENT><DEDENT><DEDENT>elif isinstance(object_, (list, set, tuple)):<EOL><INDENT>for index, item in enumerate(object_):<EOL><INDENT>_flatten(item, _construct_key(key, separator, index))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>flattened_dict[key] = object_<EOL><DEDENT><DEDENT>_flatten(nested_dict, None)<EOL>return flattened_dict<EOL>
Flattens a dictionary with nested structure to a dictionary with no
hierarchy
Consider ignoring keys that you are not interested in to prevent
unnecessary processing
This is specially true for very deep objects

:param nested_dict: dictionary we want to flatten
:param separator: string to separate dictionary keys by
:param root_keys_to_ignore: set of root keys to ignore from flattening
:return: flattened dictionary