Gianni Spear
Gianni Spear

Reputation: 7924

Python: An elegant way to delete empty lists from Python dictionary

I have a dictionary as:

default = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}

I wish to eliminate the empty values as:

default = {'a': ['alpha'], 'b': ['beta','gamma']}

I wrote a function (following an example found on the web)

def remove_empty_keys(d):
    for k in d.keys():
        try:
            if len(d[k]) < 1:
                del[k]
        except:
            pass
        return(d)

I have the following questions:

1- I didn't find the mistake why it always returns following -

remove_empty_keys(default)
 {'a': ['alpha'], 'b': ['beta'], 'g': []}

2- Is there a built-in function to eliminate/delete Null/None/empty values from Python dictionary without creating a copy of the original dictionary?

Upvotes: 12

Views: 14992

Answers (7)

David
David

Reputation: 8298

If the values are all lists, so you can use their truth's, you could use itertools.compress:

from itertools import compress
d = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}
new_d = dict(compress(d.items(), d.values()))
print(new_d)  # {'a': ['alpha'], 'b': ['beta', 'gamma']}

Upvotes: 0

mike
mike

Reputation: 1764

One more option is the following (without creating a new dict):

for e in [k for k,v in default.iteritems() if len(v) == 0]: default.pop(e)

Upvotes: 2

Colonel Panic
Colonel Panic

Reputation: 137514

Michael's answer is correct.

Stepping back, you might be able to avoid creating those empty lists at all, by use of collections.defaultdict(list)

>>> import collections
>>> d = collections.defaultdict(list)
>>> d
defaultdict(<type 'list'>, {})
>>> d["hobbits"].append("Frodo")
>>> d["hobbits"].append("Sam")
>>> d
defaultdict(<type 'list'>, {'hobbits': ['Frodo', 'Sam']})

Upvotes: 1

Michael J. Barber
Michael J. Barber

Reputation: 25032

To fix your function, change del[k] to del d[k]. There is no function to delete values in place from a dictionary.

What you are doing is deleting the variable k, not changing the dictionary at all. This is why the original dictionary is always returned.

Rewritten, your function might look like:

def remove_empty_keys(d):
    for k in d.keys():
        if not d[k]:
            del d[k]

This assumes you want to eliminate both empty list and None values, and actually removes any item with a "false" value.

Upvotes: 9

Rohit Jain
Rohit Jain

Reputation: 213193

You can use dict comprehension: -

>>> default = {'a': ['alpha'], 'b': ['beta','gamma'], 'g': []}

>>> {key: value for key, value in default.iteritems() if value}
{'a': ['alpha'], 'b': ['beta', 'gamma']}

Upvotes: 5

drekyn
drekyn

Reputation: 438

dict((k, v) for k, v in default.iteritems() if v)

This filters all items which are not empty strings, empty dict/tuple/list.

Upvotes: 4

mgilson
mgilson

Reputation: 309821

There's no builtin for this (AFAIK), but you can do it easily with a dict comprehension:

new_dict = {k:v for k,v in original_dict.items() if v}

If you're stuck with an older version of python (pre 2.7 without dict comprehensions), you can use the dict constructor:

new_dict = dict((k,v) for k,v in original_dict.items() if v)

Note that this doesn't operate in place (as per your second question). And dictionaries don't support slice assignment like lists do, so the best* you can really do to get this all done in place is:

new_dict = {k:v for k,v in original_dict.items() if v}
original_dict.clear()
original_dict.update(new_dict)

*of course the term "best" is completely subjective.

Upvotes: 14

Related Questions