Duolasa
Duolasa

Reputation: 25

How can I check if a list in a list comprehension inside a dictionary comprehension is empty?

I'm currently using list comprehension inside dictionary comprehension to detect changes between 2 dictionaries with lists as values.

The code looks something like this:

detectedChanges = {table: [field for field in tableDict[table] if field not in fieldBlackList] for table in modifiedTableDict if table not in tableBlackList}

This will create a dictionary where each entry is the table name and associated with it is a list changes.

The problem I'm getting is that although this code works, the resulting structure detectedChanges is filled with entries that only contain a table name and an empty list (meaning that no changes were detected).

I'm currently doing a posterior sweep through the dictionary in order to remove these entries but I would like avoid putting them in the dictionary in the first place.

Basically if I could somehow do a length check or something over [field for field in tableDict[table] I could validade it before creating the key:value entry.

Is there way to do this with the current method I'm using?

Upvotes: 0

Views: 764

Answers (2)

Poik
Poik

Reputation: 2105

Just an addition to eumiro's answer. Please use their answer first as it is more readable. However, if I'm not mistaken comprehensions are in general faster, so there is one use case, but ONLY IF THIS IS A BOTTLENECK IN YOUR CODE. I cannot emphasize that enough.

detectedChanges = {table: [field for field in tableDict[table]
                           if field not in fieldBlackList]
                   for table in modifiedTableDict
                   if table not in tableBlackList
                   if set(tableDict[table])-set(fieldBlackList)}

Notice how ugly this is. I enjoy doing things like this to get a better understanding of Python, and due to the fact that I have had things like this be bottlenecks before. However, you should always use profiling before trying to solve issues that may not exist.

The addition to your code [...] if set(tableDict[table])-set(fieldBlackList) [...] creates a set of the entries in the current table, and a set of the blacklisted fields and gets the entries that are in the current table but not the blacklist. Empty sets evaluate to False causing the comprehension to ignore that table, the same as if it were in the tableBlackList variable. To make it more explicit, one could compare the result to an empty set or check whether it has a value in it at all.

Also, prefer the following for speed:

detectedChanges = {table: [field for field in fields
                           if field not in fieldBlackList]
                   for table, fields in modifiedTableDict.iteritems()
                   if table not in tableBlackList
                   if set(fields)-set(fieldBlackList)}

Upvotes: 0

eumiro
eumiro

Reputation: 212895

Although dict comprehensions are cool, they should not be misused. The following code is not much longer and it can be kept on a narrow screen as well:

detectedChanges = {}
for table, fields in modifiedTableDict.iteritems():
    if table not in tableBlackList:
        good_fields = [field for field in fields
                             if field not in fieldBlackList]
        if good_fields:
            detectedChanges[table] = good_fields

Upvotes: 1

Related Questions