Juan
Juan

Reputation: 13

Nested dictionary comprehension to avoid empty values

I have an api call that returns a dictionary with all the ids for all users and others to get the userDetails like:

>>> allIds=api.getAllIds()
{1,2,3,4,5}
>>> userDetails=api.getUserDetails(1)
{'name':'Bob','age':'19'}

I'm trying to pack the whole structure in a dict with the userId-like key and the info-like value.

I could make it work with:

>>> users={id:api.getUserDetails(id) for id in allIds}
{1:{'name':'bob','age':'19'},2:None,3:{'name':'alice','age':'21'},...}

The problem is that not all Ids returns a response as you can see for the id 2 call. I'm trying not to use traditional loops and I'm solving the situation cleaning the resulting dict after the calls with:

>>> users=[id:users[id] for id in users.keys() if users[id]!=None]

It's working, but I'm trying not to put inside the empty values instead of cleaning. In a normal situation you could create the dict like:

>>> a=[id:b[id] for id in b.keys() if b[id]!=None ]

But in my case if I check if b[i] is None... then I'm calling the api two times because my b[i] expression is api.getUserDetails(id), one to take the value and the other to check if is not None.

So I'm trying something like nested dictionary comprehension:

users = {(x,y) for x in usersIds for y in api.getUserDetails(x) if y!=None }

But I can not make it work.

Anyone know how to do it?

Upvotes: 1

Views: 1750

Answers (1)

Moses Koledoye
Moses Koledoye

Reputation: 78546

You can put the result of the api call in a singleton tuple:

users = {x: y for x in usersIds for y in (api.getUserDetails(x),) if y is not None}

Demo:

lst = [(5,6), (2,None)]
d = {k: v for k, x in lst for v in (x,) if v is not None}
print(d)
# {5: 6}

However, it is pretty wasteful to set up a nested loop for such and may be more readable to use a vanilla for loop to build the dictionary:

users = {}
for x in usersIds:
    y = api.getUserDetails(x)
    if y is not None:
        users[x] = y

Upvotes: 4

Related Questions