I found this GitHub gist on generating tree structures in Python. It’s a little cryptic, but it works. This method uses the collections
module which isn’t available in Python before 2.5. If that affects you, then you can use the following to simulate collections.defaultdict()
.
try: from collections import defaultdict except: class defaultdict(dict): def __init__(self, default_factory=None, *a, **kw): if (default_factory is not None and not hasattr(default_factory, '__call__')): raise TypeError('first argument must be callable') dict.__init__(self, *a, **kw) self.default_factory = default_factory def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() return value def __reduce__(self): if self.default_factory is None: args = tuple() else: args = self.default_factory, return type(self), args, None, None, self.items() def copy(self): return self.__copy__() def __copy__(self): return type(self)(self.default_factory, self) def __deepcopy__(self, memo): import copy return type(self)(self.default_factory, copy.deepcopy(self.items())) def __repr__(self): return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))
Simple Python Trees
This is the most uncomfortable/suspicious one-liner I have ever seen. (But it works.)
from collections import defaultdict Tree = lambda: defaultdict( Tree )
We can then add items, as a list of (probably) strings, to this structure with another function,
def add( t, path ): for node in path t = t[node]
Suppose we have some hierarchical data in a text file, places.txt
,
US -> Central -> Louisiana -> Monroe US -> Central -> Texas -> Midland US -> Pacific -> California -> East Palo Alto
Then we can convert this to a list of lists using some Python,
# open the file and read each line places = open( 'places.txt', 'r' ).readlines() # split by ' -> ', an arrow with spaces # NB: the .strip() takes the newline '\n' off the end places = [ i.split(' -> ').strip() for i in places ]
Then we can add places
, which is a list of lists of strings, to a tree, t
,
t = Tree() for place in places: add( t, place )
Now we have a tree of defaultdict
objects. To convert this to regular dictionaries, we can apply the following function to modify our tree in place.
dicts = lambda t: { k:dicts(t[k]) for k in t }