How to use dictionary comprehension to combine two lists into a nested dictionary?

Question:

I want to combine the following lists into a nested dictionary using list comprehension.

dates = ['2023-04-01', '2023-04-07', '2023-04-17', '2023-04-19', '2023-04-25']
events_name = [
    'PyTexas', 'PyCamp Spain', 'PyData Berlin', 'PyCon US', 'PyLadies Amsterdam']

The dictionary should look like this:

python_events = {
    0: {'time': '2023-04-01', 'name': 'PyTexas'}, 
    1: {'time': '2023-04-07', 'name': 'PyCamp Spain'},
    2: {'time': '2023-04-17', 'name': 'PyData Berlin'},
    3: {'time': '2023-04-19', 'name': 'PyCon US'},
    4: {'time': '2023-04-25', 'name': 'PyLadies Amsterdam'}}

I am trying to use dictonary comprehension mostly for learning and practice. It seems like a bad use case for comprehension since it most likely will not be readable at all, or at least doesn’t seem like it to me

My original way of creating the dict was looping through a range:

for i in range(0, len(dates)):
    python_events[i] = {"time": dates[i], "name": events_name[i]}

Even after some research, and using comprehension for non nested dicts, I never managed to get valid code for my comprehension. I tried multiple variants of this:

python_events = {
    i: {"time": date, "name": name for date, name in dict(foo).items()}
    for i, date, name in range(0, len(events))}

I’m clearly missing some fundamental knowledge here, so any help on how to do this would be much appreciated.

Asked By: duukn

||

Answers:

Yes, you can use a dict comprehension to make python_events like this:

dates = ['2023-04-01', '2023-04-07', '2023-04-17', '2023-04-19', '2023-04-25']
events_name = ['PyTexas', 'PyCamp Spain', 'PyData Berlin', 'PyCon US', 'PyLadies Amsterdam']


python_events = {i:{"time": date,"name": name } for i, (date, name) in enumerate(zip(dates,events_name))}
print(python_events)

Output as requested.

This code uses zip to iterate through your two lists at the same time and also enumerate to generate the index i.

Answered By: quamrana

Use enumerate to generate indices, and zip to combine two lists pair-wise:

from pprint import pprint

dates = ['2023-04-01', '2023-04-07', '2023-04-17', '2023-04-19', '2023-04-25']
events_name = ['PyTexas', 'PyCamp Spain', 'PyData Berlin', 'PyCon US', 'PyLadies Amsterdam']

python_events = {i: {'time': date, 'name': event}
                 for i, (date, event) in enumerate(zip(dates, events_name))}

pprint(python_events)

Output:

{0: {'name': 'PyTexas', 'time': '2023-04-01'},
 1: {'name': 'PyCamp Spain', 'time': '2023-04-07'},
 2: {'name': 'PyData Berlin', 'time': '2023-04-17'},
 3: {'name': 'PyCon US', 'time': '2023-04-19'},
 4: {'name': 'PyLadies Amsterdam', 'time': '2023-04-25'}}
Answered By: Mark Tolonen
dates = ['2023-04-01', '2023-04-07', '2023-04-17', '2023-04-19', '2023-04-25']
events_name = ['PyTexas', 'PyCamp Spain', 'PyData Berlin', 'PyCon US', 'PyLadies Amsterdam']

python_events = {i: {'time': date, 'name': name} for i, (date, name) in enumerate(zip(dates, events_name))}
print(python_events)

The enumerate() function is used in this snippet of code to retrieve the index and a tuple (date, name) for each element in the lists of compressed dates and events names. Then, a nested dictionary comprising the entries "time" and "name" is created with the index as the key.

Answered By: Bimesh Perera

The key to converting a for-loop to a comprehension is knowing the pattern. Here’s some pseudocode:

d = {}
for x in iterable:
    d[key_expression] = value_expression

That rearranges into a comprehension like this:

d = {key_expression: value_expression for x in iterable}

Note that for x in iterable is exactly the same, just at the end, and the two expressions don’t need to change at all.

So, for your code:

python_events = {
    i: {"time": dates[i], "name": events_name[i]} for i in range(0, len(dates))}

That said, you can use zip and enumerate to do this more cleanly, as others have answered.

Answered By: wjandrea
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.