Last active
May 25, 2018 20:09
-
-
Save cwells/c2ce19f730ca9f540d7280201f2e3240 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def dig(d, keys, *args): | |
"""Locate a value in a nested dictionary. | |
Args: | |
d (dict): the dictionary | |
keys (list): list of keys to index the dictionary with | |
default (value|callable): value or callable to return in case of missing key | |
Returns: | |
Value at `d[k0][k1][...]` if all keys are present | |
Value of `default` if missing key encountered | |
Raises: | |
KeyError: if missing key (unless `default` provided) | |
Accepts a nested dictionary, a sequence of keys, and an optional | |
default return value in case of an exception. | |
Given the dictionary `dict` and the keys `[k1, k2, k3]`, attempts | |
to return the value located at dict[k1][k2][k3]. | |
Unless the `default` argument is provided, a missing key will cause | |
a KeyError exception to be raised. | |
If the `default` argument is provided, it will be the return value | |
in case of a KeyError (rather than the exception). The value for | |
`default` can be either a plain value or a function. If it is a value, | |
it is returned as-is. If it is a function, the function is called | |
with the last found value and the missing key as arguments and the | |
function's return value is returned to the caller. | |
d = { 'a': { 'b': { 'c': { 'd': True } } } } | |
dig(d, ['a', 'b', 'c', 'd']) # True | |
dig(d, ['a', 'c']) # raises KeyError | |
dig(d, ['a', 'c', 'd'], None) # None | |
dig(d, ['a', 'b', 'd'], lambda v: v) # d['a']['b'] == {'c': {'d': True}} | |
""" | |
def error(d, k): raise | |
default = args[0] if args else error | |
try: | |
value = d[keys[0]] | |
except KeyError: | |
return default(d, keys[0]) if callable(default) else default | |
return dig(value, keys[1:], default) if len(keys) > 1 else value | |
d = { 'a': { 'b': { 'c': { 'd': True } } } } | |
dig(d, ['a', 'b', 'c', 'd']) # True | |
dig(d, ['a', 'e']) # raises KeyError | |
dig(d, ['a', 'b', 'e'], None) # None | |
dig(d, ['a', 'b', 'e'], lambda d, k: d) # d['a']['b'] == {'c': {'d': True}} | |
dig(d, ['a', 'b', 'e'], lambda d, k: d).setdefault('e', "Hello, world.") | |
dig(d, ['a', 'b', 'e']) # "Hello, world." | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment