Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I access a deeply nested dictionary using tuples?
    text
    copied!<p>I would like to expand on <a href="https://stackoverflow.com/questions/651794/whats-the-best-way-to-initialize-a-dict-of-dicts-in-python">the autovivification example</a> given in a previous answer from <a href="https://stackoverflow.com/users/17160/nosklo">nosklo</a> to allow dictionary access by tuple.</p> <p>nosklo's solution looks like this:</p> <hr> <pre><code>class AutoVivification(dict): """Implementation of perl's autovivification feature.""" def __getitem__(self, item): try: return dict.__getitem__(self, item) except KeyError: value = self[item] = type(self)() return value </code></pre> <p>Testing:</p> <pre><code>a = AutoVivification() a[1][2][3] = 4 a[1][3][3] = 5 a[1][2]['test'] = 6 print a </code></pre> <p>Output:</p> <pre><code>{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}} </code></pre> <hr> <p>I have a case where I want to set a node given some arbitrary tuple of subscripts. If I don't know how many layers deep the tuple will be, how can I design a way to set the appropriate node?</p> <p>I'm thinking that perhaps I could use syntax like the following: </p> <pre><code>mytuple = (1,2,3) a[mytuple] = 4 </code></pre> <p>But I'm having trouble coming up with a working implementation.</p> <hr> <h1>Update</h1> <p>I have a fully working example based on @JCash's answer:</p> <pre><code>class NestedDict(dict): """ Nested dictionary of arbitrary depth with autovivification. Allows data access via extended slice notation. """ def __getitem__(self, keys): # Let's assume *keys* is a list or tuple. if not isinstance(keys, basestring): try: node = self for key in keys: node = dict.__getitem__(node, key) return node except TypeError: # *keys* is not a list or tuple. pass try: return dict.__getitem__(self, keys) except KeyError: raise KeyError(keys) def __setitem__(self, keys, value): # Let's assume *keys* is a list or tuple. if not isinstance(keys, basestring): try: node = self for key in keys[:-1]: try: node = dict.__getitem__(node, key) except KeyError: node[key] = type(self)() node = node[key] return dict.__setitem__(node, keys[-1], value) except TypeError: # *keys* is not a list or tuple. pass dict.__setitem__(self, keys, value) </code></pre> <p>Which can achieve the same output as above using extended slice notation:</p> <pre><code>d = NestedDict() d[1,2,3] = 4 d[1,3,3] = 5 d[1,2,'test'] = 6 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload