Python3 Removing dictionary key if value contained in list is blank

236 views Asked by At

So I have a dictionary filled with lots of useful stuff. I would like to remove a key (build a new dict without the key) if any value within a list is empty.

The dictionary:

>>>print(vaar123)
{'moo': 'cora', 'ham': ['', 'test'], 'bye': 2, 'pigeon': '', 'heloo': 1}

I can remove the 'pigeon' key with its empty value with something along the lines of.

>>>dict((k, v) for k, v in vaar123.items() if v)
{'moo': 'cora', 'ham': ['', 'test'], 'heloo': 1, 'bye': 2}

But try as I might, I cannot seem to come up with a method to remove 'ham' as it has an empty value in its list.

Thanks in advance for any suggestions, Frank

Info: The dictionary is built with a value on creation (set by admin) the additional value is added to the list by user input. The value pair is used as output. Having a single value in the list produces undesirable output.

3

There are 3 answers

0
Patrick Haugh On BEST ANSWER

This function recursively checks Sized Iterables to see if they are empty and returns False if it finds one that is

from collections.abc import Sized, Iterable #If you're on Python >= 3.6,
                                            #you can use collections.abc.Collection

def all_nonempty(v):
    if isinstance(v, (Sized, Iterable)):
        return v and (all(map(all_nonempty, v)) if not isinstance(v, str) else True)
        #We do the check against str because 'a' is a sized iterable that
        #contains 'a'.  I don't think there's an abstract class for
        #containers like that
    return True

Then we can use this to winnow the dict

print({k: v for k, v in d.items() if all_nonempty(v)})

outputs:

{'moo': 'cora', 'bye': 2, 'heloo': 1}
0
John Coleman On

Perhaps like this:

>>> d = {'moo': 'cora', 'ham': ['', 'test'], 'heloo': 1, 'bye': 2}
>>> {k:v for k,v in d.items() if not(isinstance(v,list) and len(v) > 0 and v[0] == '')}
{'heloo': 1, 'moo': 'cora', 'bye': 2}

Or maybe just:

>>> {k:v for k,v in d.items() if not(isinstance(v,list) and '' in v)}
{'heloo': 1, 'moo': 'cora', 'bye': 2}

The first answer will remove items where the values are lists in which the first element is ''. The second will remove any value which is a list in which '' occurs somewhere.

0
BallpointBen On

Assuming all values in the lists are strings:

{k: v
 for k, v in vaar123.items()
 if (not hasattr(v, '__iter__')) or
    (hasattr(v, '__iter__') and v and all(elem for elem in v))}

Explanation: Keep non-iterable values because they can't be empty (doesn't make sense). Otherwise, if a value is iterable, discard it if it's empty or if it contains any false values (i.e., empty string per the assumption above).