def flatten_dict(d):
    """Flatten a dictionary where values may be other dictionaries

    The dictionary returned will have keys created by joining higher- to lower-level keys with dots. e.g. if the original dict d is
    {'a': {'x':3, 'y':4}, 'b':{'z':5}, 'c':{} }
    then the dict returned will be
    {'a.x':3, 'a.y': 4, 'b.z':5}

    Note that if a key is mapped to an empty dict or list, NO key in the returned dict is created for this key.

    Also note that values may be overwritten if there is conflicting dot notation in the input dictionary, e.g. {'a': {'x': 3}, 'a.x': 4}.
    """
    # http://codereview.stackexchange.com/a/21035

    def expand(key, value):
        if isinstance(value, list):
            value = {i: v for (i, v) in enumerate(value)}
        if isinstance(value, dict):
            return [
                (str(key) + "." + str(k), v) for k, v in flatten_dict(value).items()
            ]
        else:
            return [(key, value)]

    items = [item for k, v in d.items() for item in expand(k, v)]

    return dict(items)