sciris.sc_nested

Nested dictionary functions.

Functions

flattendict

Flatten nested dictionary

getnested

Get the value for the given list of keys

iternested

Return a list of all the twigs in the current dictionary

makenested

Little functions to get and set data from nested dictionaries.

mergenested

Merge different nested dictionaries

nestedloop

Zip list of lists in order

search

Find a key or attribute within a dictionary or object.

setnested

Set the value for the given list of keys

getnested(nesteddict, keylist, safe=False)[source]

Get the value for the given list of keys

>>> sc.getnested(foo, ['a','b'])

See sc.makenested() for full documentation.

setnested(nesteddict, keylist, value, force=True)[source]

Set the value for the given list of keys

>>> sc.setnested(foo, ['a','b'], 3)

See sc.makenested() for full documentation.

makenested(nesteddict, keylist=None, value=None, overwrite=False, generator=None)[source]

Little functions to get and set data from nested dictionaries.

The first two were adapted from: http://stackoverflow.com/questions/14692690/access-python-nested-dictionary-items-via-a-list-of-keys

“getnested” will get the value for the given list of keys:

>>> sc.getnested(foo, ['a','b'])

“setnested” will set the value for the given list of keys:

>>> sc.setnested(foo, ['a','b'], 3)

“makenested” will recursively update a dictionary with the given list of keys:

>>> sc.makenested(foo, ['a','b'])

“iternested” will return a list of all the twigs in the current dictionary:

>>> twigs = sc.iternested(foo)

Example 1:

foo = {}
sc.makenested(foo, ['a','b'])
foo['a']['b'] = 3
print(sc.getnested(foo, ['a','b']))    # 3
sc.setnested(foo, ['a','b'], 7)
print(sc.getnested(foo, ['a','b']))    # 7
sc.makenested(foo, ['bar','cat'])
sc.setnested(foo, ['bar','cat'], 'in the hat')
print(foo['bar'])  # {'cat': 'in the hat'}

Example 2:

foo = {}
sc.makenested(foo, ['a','x'])
sc.makenested(foo, ['a','y'])
sc.makenested(foo, ['a','z'])
sc.makenested(foo, ['b','a','x'])
sc.makenested(foo, ['b','a','y'])
count = 0
for twig in sc.iternested(foo):
    count += 1
    sc.setnested(foo, twig, count)   # {'a': {'y': 1, 'x': 2, 'z': 3}, 'b': {'a': {'y': 4, 'x': 5}}}

Version: 2014nov29

iternested(nesteddict, previous=None)[source]

Return a list of all the twigs in the current dictionary

>>> twigs = sc.iternested(foo)

See sc.makenested() for full documentation.

mergenested(dict1, dict2, die=False, verbose=False, _path=None)[source]

Merge different nested dictionaries

See sc.makenested() for full documentation.

Adapted from https://stackoverflow.com/questions/7204805/dictionaries-of-dictionaries-merge

flattendict(nesteddict, sep=None, _prefix=None)[source]

Flatten nested dictionary

Example:

>>> sc.flattendict({'a':{'b':1,'c':{'d':2,'e':3}}})
{('a', 'b'): 1, ('a', 'c', 'd'): 2, ('a', 'c', 'e'): 3}
>>> sc.flattendict({'a':{'b':1,'c':{'d':2,'e':3}}}, sep='_')
{'a_b': 1, 'a_c_d': 2, 'a_c_e': 3}
Parameters
  • d – Input dictionary potentially containing dicts as values

  • sep – Concatenate keys using string separator. If None the returned dictionary will have tuples as keys

  • _prefix – Internal argument for recursively accumulating the nested keys

Returns

A flat dictionary where no values are dicts

search(obj, attribute, _trace='')[source]

Find a key or attribute within a dictionary or object.

This function facilitates finding nested key(s) or attributes within an object, by searching recursively through keys or attributes.

Parameters
  • obj – A dict or class with __dict__ attribute

  • attribute – The substring to search for

  • _trace – Not for user input - internal variable used for recursion

Returns

A list of matching attributes. The items in the list are the Python strings used to access the attribute (via attribute or dict indexing)

Example:

nested = {'a':{'foo':1, 'bar':2}, 'b':{'bar':3, 'cat':4}}
matches = sc.search(nested, 'bar') # Returns ['["a"]["bar"]', '["b"]["bar"]']
nestedloop(inputs, loop_order)[source]

Zip list of lists in order

This function takes in a list of lists to iterate over, and their nesting order. It then yields tuples of items in the given order. Only tested for two levels but in theory supports an arbitrary number of items.

Parameters
  • inputs (list) – List of lists. All lists should have the same length

  • loop_order (list) – Nesting order for the lists

Returns

Generator yielding tuples of items, one for each list

Example usage:

>>> list(sc.nestedloop([['a','b'],[1,2]],[0,1]))
[['a', 1], ['a', 2], ['b', 1], ['b', 2]]

Notice how the first two items have the same value for the first list while the items from the second list vary. If the loop_order is reversed, then:

>>> list(sc.nestedloop([['a','b'],[1,2]],[1,0]))
[['a', 1], ['b', 1], ['a', 2], ['b', 2]]

Notice now how now the first two items have different values from the first list but the same items from the second list.

From Atomica by Romesh Abeysuriya.

New in version 1.0.0.