Search code examples
pythonpython-3.xdictionarydictionary-comprehensiondict-comprehension

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?


Solution

  • 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