One of the best ways I've ever seen an implementation of nested dictionaries is to Aaron Hall to answer the question. What is the best way to implement nested dictionaries? . This is an example implementation of a type that performs Autovivification in a Perl programming language.
In any case, using one here would be useful, because that means you only need to call setdefault() on the "leaves" of your data tree structure (which are list s, not sub-dictionaries).
So here is the answer to your question that uses it:
from collections import namedtuple from functools import reduce from operator import attrgetter from pprint import pprint Holding = namedtuple('Holding', ['portfolio', 'ticker', 'shares']) lst = [Holding('Large Cap', 'TSLA', 100), Holding('Large Cap', 'MSFT', 200), Holding('Small Cap', 'UTSI', 500),] def indexer(lst, indexes): """ Creates a dynamic nested dictionary based on indexes. """ class Vividict(dict): """ dict subclass which dynamically creates sub-dictionaries when they're first referenced (and don't exist). See /questions/32317/what-is-the-best-way-to-implement-nested-dictionaries/236492#236492 """ def __missing__(self, key): value = self[key] = type(self)() return value result = Vividict() index_getters = attrgetter(*indexes) for item in lst: *indices, leaf = index_getters(item)
Output:
{'Large Cap': {'MSFT': [Holding(portfolio='Large Cap', ticker='MSFT', shares=200)], 'TSLA': [Holding(portfolio='Large Cap', ticker='TSLA', shares=100)]}, 'Small Cap': {'UTSI': [Holding(portfolio='Small Cap', ticker='UTSI', shares=500)]}} {'Large Cap': {'MSFT': {200: [Holding(portfolio='Large Cap', ticker='MSFT', shares=200)]}, 'TSLA': {100: [Holding(portfolio='Large Cap', ticker='TSLA', shares=100)]}}, 'Small Cap': {'UTSI': {500: [Holding(portfolio='Small Cap', ticker='UTSI', shares=500)]}}}