Skip to content

Mastering Nested Data Structures in Python: Guide to Lists of Dicts and Dicts of Lists

Updated: at 04:12 AM

Python provides powerful, flexible data structures that allow programmers to organize and store data in nested combinations. Two common examples of nested data structures in Python are lists of dictionaries and dictionaries of lists. Mastering these nested combinations unlocks the ability to model complex real-world data relationships in code.

This guide will provide Python developers with a comprehensive walkthrough of working with these nested data structures. Read on to learn about:

Table of Contents

Open Table of Contents

Python Lists and Dictionaries Refresher

Before diving into nested data structures, let’s quickly review the fundamentals of Python lists and dictionaries - the building blocks of nested collections.

Python Lists

A Python list is an ordered collection of objects enclosed in square brackets []. Lists can contain elements of any data type, including other lists to form nested lists.

# Lists in Python

nums = [1, 2, 3]
fruits = ['apples', 'bananas', 'pears']
mixed = [1, 'two', 3.0, True]
nested = [[1,2], [3,4], [5,6]]

We can access, modify, add, and remove list elements using indexing and methods like append() and remove().

# Accessing, modifying lists

print(fruits[1]) # 'bananas'
fruits[1] = 'grapes'
fruits.append('mangos')
fruits.remove('apples')

Python Dictionaries

A dictionary consists of key-value pairs enclosed in curly braces {}. Dict keys must be unique within a dictionary while values can be duplicated.

# Dictionaries in Python

capitals = {'USA':'Washington DC', 'India':'New Delhi'}
user = {'name':'John', 'id':1234, 'email':'[email protected]'}

Access dictionary values by key, add new key-value pairs, modify values for existing keys, and remove keys using syntax like:

# Accessing, modifying dictionaries

print(capitals['India']) # 'New Delhi'

capitals['Russia'] = 'Moscow'
user['name'] = 'Jane'

del capitals['USA']

Now that we’ve reviewed the basics of Python’s fundamental collection types - lists and dictionaries - let’s look at combining them to model complex data.

Why Nested Data Structures?

Before we dive into the syntax, it’s important to understand why you may want to nest lists and dictionaries in Python. Why not keep everything separate in flat data structures?

Some key reasons to use nested data structures include:

Now let’s look at ways to create these nested structures in Python code.

Constructing Nested Data Structures

Lists of Dictionaries

A common nested data structure in Python is a list of dicts. Each element in the outer list is a dictionary containing related key-value pairs.

For example, we can store a list of user profiles, where each user is represented by a dict with keys like “name”, “email”, “id” etc:

# List of dictionaries

users = [
  { 'name':'John', 'email':'[email protected]', 'id':1234 },
  { 'name':'Mary', 'email': '[email protected]', 'id': 4567 },
  { 'name':'Peter', 'email':'[email protected]', 'id':8910 }
]

We would access all the data for user John through users[0], Mary through users[1] and so on.

Some key points about lists of dicts:

Dictionaries of Lists

Another useful combination is a dictionary of lists. Here each dict key stores a list value.

For example, we can store a set of purchases by category:

# Dictionary of lists

purchases = {
  'electronics': ['laptop', 'tv', 'smartphone'],
  'toys': ['legos', 'puzzles', 'football'],
  'clothing': ['shirts', 'pants', 'dresses']
}

Some common uses for dictionaries of lists:

These examples demonstrate the flexibility of nested data structures for modeling real-world data relationships in code.

Accessing and Modifying Nested Data

Now that we can construct lists of dicts and dicts of lists, let’s look at techniques to access and modify elements within these nested structures.

Accessing Nested Elements

To access nested data, we chain indexing or key operations together to “drill down” into the data structure.

For example, to access user Mary’s email from our list of user dicts, we would use:

# Access nested elements

users[1]['email'] # '[email protected]'

We index the outer list first with [1], then the dict with [‘email’] to get the value.

Similarly, to get the first purchase in the ‘toys’ category from our dict of lists:

purchases['toys'][0] # 'legos'

We can continue chaining indices and keys arbitrarily deep to access nested elements in complex data structures.

Modifying Nested Elements

To modify nested data, we combine indexing/key operations with value assignment.

For example, to change Mary’s email address:

users[1]['email'] = '[email protected]'

And to add a new clothing purchase:

purchases['clothing'].append('scarf')

All the standard list methods like .append() and .remove(), along with dict operations work on nested structures in this way.

One important note is that care must be taken when modifying mutable values like lists or dicts. For example:

my_list = [ [1,2], [3,4] ]

sub_list = my_list[0]  # Points to same object
sub_list.append(5)

print(my_list) # [[1,2,5], [3,4]]

Here sub_list points to the same list object as my_list[0]. Changes to one will affect the other. To avoid this, make a copy first before modifying:

sub_list = my_list[0][:] # Copy
sub_list.append(5)

Iterating Through Nested Data Structures

Iterating through nested lists and dictionaries requires some special techniques compared to flat data structures.

Iterating Through Lists of Dicts

To process a list of dicts, we:

  1. Iterate through the outer list
  2. Access each inner dict
  3. Work with the dict’s keys/values

For example:

for user in users:
  print(user['name']) # Print each user's name

  user['logged_in'] = True # Mark them logged in

We can also directly access both the index and dict together:

for i, user in enumerate(users):
  print(f"User {i} is {user['name']}")

Iterating Through Dicts of Lists

For dictionaries of lists, we:

  1. Loop through the dictionary’s keys
  2. Access each inner list value
  3. Iterate through the list contents

For example:

for category, purchases in purchases.items():
  print(f"{category}: {purchases}")

  for purchase in purchases:
    print(purchase)

This allows us to access both the outer key and inner list values during iteration.

Using Nested Loops

For additional processing, we can add nested for loops to iterate through multiple levels:

for user in users:
  for key, value in user.items():
    print(f"{key}: {value}")

The inner loop iterates through each dict within the outer list.

Nested loops allow performing any arbitrary processing on the different levels of nested data structures.

Built-in Functions for Nested Data Structures

Python provides several built-in functions that are useful when working with nested lists and dictionaries:

For example:

# Length of outer list

num_users = len(users)

# Sum all purchases

total_purchases = sum(len(v) for v in purchases.values())

# Sort users by id

sorted_users = sorted(users, key=lambda user: user['id'])

These built-ins make it easy to work with nested data structures without extensive looping yourself.

Best Practices for Nested Data Manipulations

When working with nested data structures in Python, keep these best practices in mind:

Mastering these nested data structure best practices will lead to more readable, maintainable Python codebases.

Applications of Nested Data Structures

Let’s briefly highlight some real-world examples of where nested Python data structures are commonly used:

The options are endless for modeling domain data in nested Python data structures.

Conclusion

This guide covered the fundamentals of working with nested lists of dictionaries and dictionaries of lists in Python. We explored:

The key takeaways are:

With this knowledge, you are now equipped to harness the power of nested data structures in your own Python programs!