Skip to content

Stanford-ILIAD/attrdict

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AttrDict

This package contains a generic dictionary AttrDict, which implements nested dictionaries that are easy to access, filter, combine, and write to.

Installation: pip install attr-dicts:

PyPI: https://pypi.org/project/attr-dicts/

Creation: Let's say we want to store the following nested structure of arrays:

- food
    - carrot: [1,2,3]
    - apple: [4,5,6]
    - broccoli: [7,8,9,10]
- utensils
    - fork
        - three_prong: [11,12]
        - four_prong: [13,14,15]
    - spoon: [16,17,18]

AttrDicts use '/' to separate keys, and this is built in to read/write operations. Here's two examples of how to instantiate the above structure.

d = AttrDict()
d['food/carrot'] = [1,2,3]
d.food.apple = [4,5,6]
d['food/broccoli'] = [7,8,9,10]
d['utensils/fork/three_prong'] = [11,12]
d['utensils/fork/four_prong'] = [13,14,15]
d['utensils/spoon'] = [16,17,18]

Note that both indexing and dot access work, since AttrDicts inherit from the DotMap class. Here's a slightly less effort way:

d = AttrDict(
    food=AttrDict(carrot=[1,2,3], apple=[4,5,6], broccoli=[7,8,9,10]),
    utensils=AttrDict(
        fork=AttrDict(three_prong=[11,12], four_prong=[13,14,15]), 
        spoon=[16,17,18]
    )
)

Access: There are several ways to access an AttrDict.

  1. d['utensils/fork/three_prong']: standard dictionary access, but using '/' to implicitly sub-index (KeyError if missing)
  2. d.utensils.fork.three_prong: dotmap access (AttributeError if missing)
  3. d.utensils['fork/three_prong']: mixed indexing + dotmap (either AttributeError or KeyError if missing)
  4. d >> 'utensils/fork/three_prong: (DEPRECATED) required key access, will error if not present.
  5. d << 'utensils/fork/three_prong: optional key access, will return None if not present
  6. d > ['utensils/fork/three_prong,'utensils/spoon']: required key filtering, returns sub-dict. errors if a key in the arg list is not present.
  7. d < ['utensils/fork/three_prong,'utensils/spoon']: optional key access, returns sub-dict, ignores keys that aren't present.

Node/Leaf operations: Leaf nodes are any access pattern that returns something that isn't an AttrDict. In the above example, 'food' is a node key, while 'food/carrot' is a leaf key. We can operate on all leaf nodes at once, here are some example methods:

  1. d.leaf_keys(): Generator that yields leaf keys under a depth first traverse.
  2. d.list_leaf_keys(): Outputs a list instead of generator.
  3. d.leaf_values(): Generator that yields leaf values under a depth first traverse.
  4. applied_d = d.leaf_apply(lambda v: <new_v>): Apply a function(value) on all leaf values, and create a new AttrDict.
  5. filtered_d = d.leaf_filter(lambda k,v: <condition>): Only keep leaf keys where condition is true in new AttrDict.

Similarly, there are functions that operate on both nodes and leaves.

Combining: Combining AttrDicts can be done in several ways:

  1. new_d = d1 & d2: Standard join, returns a new AttrDict, which will favor keys from d2 if there are duplicates.
  2. d1.combine(d2): Mutates d1 to join the arrays.
  3. new_d = AttrDict.leaf_combine_and_apply([d1, d2, ...], lambda vs: <return one value>): Given a list of AttrDicts with the same keys, will create one AttrDict where the value for a given key k is some function of vs = [d1[k], d2[k], ...].

About

Dictionary for accessing nested keys

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages