[Tutor] creating dict of dict : similar to perl hash of hash

Alan Gauld alan.gauld at btinternet.com
Wed Mar 7 00:21:09 CET 2012


On 06/03/12 18:18, Martin A. Brown wrote:

>   : $hash->{$a}->{$b}->{$c} = "value";
>   : if (exists $hash->{$a}->{$b}->{$c} ){ print "found value"}
>
> Autovivifying.  That's what the perl-heads call that.

Aha!, that brought it back, now I know what it does...

>    >>>  import collections
>    >>>  d = collections.defaultdict(collections.defaultdict)
>    >>>  a,b,c = range(3)
>    >>>  d[a][b] = c
>    >>>  d
>    defaultdict(<type 'collections.defaultdict'>, {0: defaultdict(None, {1: 2})})

Unfortunately this fails at 3 levels as per the OP example.
The second level dict supplies a default value of None.

If you know the max number of depths you can do something
like this:

 >>> from collections import defaultdict as dd
 >>> d3 = dd(lambda : dd( lambda : dd() ) )
 >>> d3['a']['b']['c'] = 'value'
 >>> d3
defaultdict(<function <lambda> at 0x7f3aefa4e758>, {'a': 
defaultdict(<function <lambda> at 0x7f3aefa4e6e0>, {'b': 
defaultdict(None, {'c': 'value'})})})
 >>>

But it doesn't have the same dynamic depth that the Perl version has, 
you need to know your maximum depth. The last level will always have the 
default set to None.

You could create a class subclassed from defaultdict that would do it 
though...

Unless of course somebody else can think of a more elegant solution.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/



More information about the Tutor mailing list